wpf datagrid отображать строку после обновления данных

У меня есть датагрид (один из столбцов - время) с фильтром. Перед использованием фильтра пользователь может прокрутить вниз, например, до 14:00.
После использования фильтра первая отображаемая строка в сетке данных должна быть 14:00 (предполагается, что эта строка присутствует всегда)

У меня есть два метода:
1. Вызов перед сбросом сетки данных itemsSource

    Statistics.ScrollPositionData GetScrollPosition()
    {
        try
        {
            if (VisualTreeHelper.GetChildrenCount(dg_timing) > 0)
            {
                var border = VisualTreeHelper.GetChild(dg_timing, 0) as Decorator;
                if (border != null)
                {
                    var scroll = border.Child as ScrollViewer;
                    if (scroll != null)
                    { 
                        var view = CollectionViewSource.GetDefaultView(dg_timing.ItemsSource) as CollectionView;                          
                        DataRowView firstItem = view.GetItemAt((int)scroll.VerticalOffset) as DataRowView; //here is incorrect code
                        return new Statistics.ScrollPositionData()
                        {
                            offset = scroll.VerticalOffset,
                            rowId = (firstItem.Row.ItemArray[((Statistics)DataContext).GetColumnOrder("Timeline")] as TextBlock).Text
                        };
                    }
                }
            }
        }
        catch (Exception) { }
        return null;
    }
  1. Вызов после сброса сетки данных itemsSource

    void SetScrollPosition(Statistics.ScrollPositionData offset)
    {
        try
        {
            if (offset != null)
            {
                var t1 = (CollectionViewSource.GetDefaultView(dg_timing.ItemsSource) as CollectionView);                     
                var t2 = t1.Cast<DataRowView>();
                var row = t2.
                    LastOrDefault(w =>
                    {
                        string t = (w.Row.ItemArray[((Statistics)DataContext).GetColumnOrder("Timeline")] as TextBlock).Text;
                        long l1 = DateTime.ParseExact(t, @"mm\:ss\:ff", CultureInfo.InvariantCulture).Ticks;
                        long l2 = DateTime.ParseExact(offset.rowId, @"mm\:ss\:ff", CultureInfo.InvariantCulture).Ticks;
                        return t == offset.rowId || l1 < l2;
                        });                     
                var border = VisualTreeHelper.GetChild(dg_timing, 0) as Decorator;
                if (border != null)
                {
                    var scroll = border.Child as ScrollViewer;
                    if (scroll != null)
                    {
                        scroll.ScrollToBottom();
                        if (row != null)
                        {
                            dg_timing.SelectedItem = row;
                            dg_timing.ScrollIntoView(row);
                        }
                        else
                        {
                            scroll.ScrollToVerticalOffset(offset.offset);
                        }
                    }
                } 
            }
        }
        catch (Exception) { }
    }
    

Проблема в том, чтобы найти первую строку отображения в сетке данных

PS спасибо @habib с помощью текстового редактора

1 ответ

Я думаю, что нашел полное объяснение HowTo с примером listview

код будет

 Statistics.ScrollPositionData GetScrollPosition()
    {
        try
        {
            if (VisualTreeHelper.GetChildrenCount(dg_timing) > 0)
            {
                var border = VisualTreeHelper.GetChild(dg_timing, 0) as Decorator;
                if (border != null)
                {
                    var scroll = border.Child as ScrollViewer;
                    if (scroll != null)
                    {
                        return new Statistics.ScrollPositionData()
                        {
                            offset = (int)scroll.VerticalOffset,
                            rowId =  (((DataRowView)dg_timing.Items[(int)scroll.VerticalOffset]).Row.ItemArray[((Statistics)DataContext).GetColumnOrder("Timeline")] as TextBlock).Text
                        };
                    }
                }
            }
        }
        catch (Exception) { }
        return null;
    }

Но сейчас у меня другая проблема - с виртуализацией.

Если я установлю

EnableRowVirtualization="True" 
EnableColumnVirtualization="True" 
VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"  

и прокрутите вниз, обновите данные, я получу несколько строк сверху, но после прокрутки вверх и назад строки верны. EnableRowVirtualization="False" решает проблему, но DataGrid с 3000 строк загружается слишком медленно

Другие вопросы по тегам