2009-03-18 3 views
7

У меня есть WPF DataGrid, который, когда слишком много строк для просмотра на экране, получает вертикальную полосу прокрутки. Я хотел бы знать, есть ли способ узнать, что такое верхняя видимая строка, когда пользователь прокручивает.Проверить видимые строки в WPF DataGrid

В идеале, я хотел бы иметь возможность подключать событие, чтобы знать, когда пользователь прокручивает и прокручивает, проверьте, какая строка видимости для обновления, чтобы обновить некоторую информацию.

ответ

0

Это своего рода сложный способ сделать это, но это может сработать. Во-первых, подкласс DataGridRowsPresenter и переопределить OnViewportOffsetChanged method. Затем дублируйте стандартный шаблон управления для datagrid и замените DataGridRowsPresenter своим собственным. Я оставляю детали тестирования ударов для строки относительно области просмотра до вас ;-).

Что вы пытаетесь выполнить, в частности? Возможно, мы сможем найти лучший способ, так как это может быть очень хрупким и требует кучу дополнительной работы (т. Е. Синхронизировать шаблон управления, если они его обновят).

+0

Спасибо. Я обошел его, просто увеличив то, что находится в сетке (главным образом, шрифты), используя анимацию. Не совсем так просто, но в основном то, что я хотел. –

+0

У меня возникла проблема с масштабированием шрифта, что при масштабировании шрифта вниз столбцы не будут автоматически изменяться, поэтому они будут по-прежнему шириной большего размера шрифта. –

+0

Печально ошибка в текущей сборке WPFToolkit, которая заставляет столбцы автоматического изменения размера работать странно, когда они смешиваются со столбцами Star. Мы также видим это поведение, и мы так и не удосужились его исправить. –

3

Используя следующий метод работал для меня:

// mHorizontalScrollBar is the HorizontalScrollBar subclass control's instance 

// Get the total item count 
nTotalCount = DataGrid1.Items.Count; 

// Get the first visible row index 
nFirstVisibleRow = mHorizontalScrollBar.Value; 

// Get the last visible row index 
nLastVisibleRow = nFirstVisibleRow + nTotalCount - mHorizontalScrollBar.Maximum; 
+0

@ DannyBeckett, редактировать делает ответ совершенно бесполезным (или, что ж, очень неясно), возвращаясь к исходному ответу. – Sinatr

+1

@Sinatr Я не согласен, и я отбросил ваши изменения. Если вы все еще не согласны, отправьте вопрос Meta Stack Exchange вместо того, чтобы начать откат войны. –

+0

@ DannyBeckett, прежде чем он стал чистым пошаговым руководством (я согласен с несколько плохим языком), и я уверен, что в то время были даны подсказки. Теперь я запускаю одну и ту же проблему, и, пытаясь ответить на этот вопрос в текущем состоянии, я не могу заставить его работать и даже понизить его. Затем я вижу ваше редактирование и читаю оригинальный ответ, который является более понятным. Оставим это как есть. Будущие читатели все равно будут видеть мой комментарий (но не все из них смогут увидеть ревизии, я думаю, а не мои проблемы;). – Sinatr

2

Как о подписке на событие ScrollViewer.ScrollChanged на ScrollViewer в DataGrid в? Аргументы события для него довольно обширны, описывая, сколько движется ScrollViewer и каково его новое вертикальное смещение. Кроме того, в соответствии с MSDN:

Если CanContentScroll верно, то значение свойств ExtentHeight, ScrollableHeight, ViewportHeight и VerticalOffset является количеством элементов. Если CanContentScroll является ложным, значениями этих свойств являются независимые от устройства пиксели.

CanContentScroll действительно имеет значение для ScrollViewer для DataGrid.

Все, что вам нужно сделать, это найти ScrollViewer:

ScrollViewer scrollview = FindVisualChild<ScrollViewer>(dataGrid); 

с помощью реализации FindVisualChild, которые можно найти в разных местах (например, здесь: Finding control within WPF itemscontrol).

+0

Это действительно хороший и прочный подход. – Gerard

0

Детектирование скроллинг так же легко, как

<DataGrid ScrollViewer.ScrollChanged="DataGrid_ScrollChanged" /> 

Теперь вы должны получить ScrollViewer экземпляр:

void DataGrid_ScrollChanged(object sender, RoutedEventArgs e) 
{ 
    var scroll = FindVisualChild<ScrollViewer>((DependencyObject)sender); 
    ... 
} 

(Не уверен, где происхождение FindVisualChild, но существует множество реализаций, например here)

И тогда вы можете

int firstRow = (int)scroll.VerticalOffset; 
int lastRow = (int)scroll.VerticalOffset + (int)scroll.ViewportHeight + 1;