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;
}
Вызов после сброса сетки данных 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 строк загружается слишком медленно