2008-11-16 3 views
6

Я пытаюсь синхронизировать горизонтальное положение прокрутки WPF DataGrid управления.позиции Синхронизация прокрутки для 2 WPF DataGrids

Я подписываюсь на ScrollChanged события первого DataGrid:

<toolkit:DataGrid x:Name="SourceGrid" ScrollViewer.ScrollChanged="SourceGrid_ScrollChanged"> 

У меня есть второй DataGrid:

<toolkit:DataGrid x:Name="TargetGrid"> 

В обработчик событий я пытался использовать IScrollInfo.SetHorizontalOffset, но, увы, DataGrid не обнажает IScrollInfo:

private void SourceGrid_ScrollChanged(object sender, ScrollChangedEventArgs e) 
{ 
    ((IScrollInfo)TargetGrid).SetHorizontalOffset(e.HorizontalOffset); 
    // cast to IScrollInfo fails 
} 

Есть ли другой способ сделать это? Или есть еще один элемент TargetGrid, который предоставляет необходимый IScrollInfo для достижения синхронизации позиций прокрутки?

BTW, я с использованием замороженных столбцов, поэтому я не могу обернуть оба элемента управления DataGrid с помощью ScrollViewers.

ответ

3

В соответствии с группой продуктов Microsoft перемещение визуального дерева для поиска ScrollViewer является рекомендуемым методом, как explained in their answer on Codeplex.

+0

Да. Тем не менее, я сделал то же самое в прошлом. Похоже, нам не нужно было взламывать визуальное дерево таким образом. Еще один способ, по которому WPF грубо по краям. – PeterAllenWebb 2009-05-13 14:32:08

1

У нас была эта же проблема при использовании сетки Infragistics, потому что она не (до сих пор нет) поддерживает замороженные столбцы. Таким образом, у нас было две сетки, которые были сделаны, чтобы выглядеть как один. Сетка слева не прокручивалась по горизонтали, а сетка справа. Бедные люди в замороженных колоннах.

В любом случае, мы закончили тем, что просто достигли визуального дерева и вытащили ScrollViewer. В конце концов, мы знали, что он был там - он просто не был выставлен объектной моделью. Вы можете использовать аналогичный подход, если сетка WPF не предоставляет ScrollViewer. Или вы можете подклассифицировать сетку и добавить необходимые функции для выполнения этой работы.

Заинтересованы в том, чтобы узнать, зачем вам это нужно.

+0

У меня есть источник для DataGrid Toolfit WPF из Codeplex, поэтому я мог бы найти его и разоблачить (не мой предпочтительный метод). king 2, чтобы получить эффект замороженной панели (ala Excel). – 2008-11-16 16:16:37

0

Это отличное решение. Работала отлично для меня в WPF.

http://www.codeproject.com/Articles/39244/Scroll-Synchronization

Я только что сделал ссылку на DLL ScrollSynchronizer, добавлен импорт XML:

Xmlns: прокручивать = "CLR-имен: ScrollSynchronizer"

тогда только что добавили это к обоим моим DataGrids и качается дядя:

<DataGrid.Resources> 
    <Style TargetType="ScrollViewer"> 
    <Setter Property="scroll:ScrollSynchronizer.ScrollGroup" Value="Group1" /> 
    </Style> 
</DataGrid.Resources> 
1

Вы можете обмануть в DataGrid, чтобы выставить свою ScrollViewer в качестве государственной собственности для каждой сетки, когда для example innerGridControl_ScrollChanged() обработчик, вызываемый во время инициализации usercontrol. Чтобы открыть его, вы можете сделать свою сетку в файле xaml View, а затем составить два из них в другом представлении xaml. Ниже код на innerGrid.xaml.cs, например:

public ScrollViewer Scroller { get; set; } // exposed ScrollViewer from the grid 
    private bool _isFirstTimeLoaded = true; 

    private void innerGridControl_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     if (_isFirstTimeLoaded) // just to save the code from casting and assignment after 1st time loaded 
     { 
      var scroller = (e.OriginalSource) as ScrollViewer; 
      Scroller = scroller; 
      _isFirstTimeLoaded = false; 
     } 
    } 

на OuterGridView.xaml поместить вложенное определение обработчика событий:

<Views:innerGridView Grid.Row="1" Margin="2,0,2,2" DataContext="{Binding someCollection}" 
             x:Name="grid1Control" 
             ScrollViewer.ScrollChanged="Grid1Attached_ScrollChanged" 
             ></Views:innerGridView> 

<Views:innerGridView Grid.Row="3" Margin="2,0,2,2" DataContext="{Binding someCollection}" 
             x:Name="grid2Control" 
             ScrollViewer.ScrollChanged="Grid2Attached_ScrollChanged" 
             ></Views:innerGridView> 

затем получить доступ, что общественное ScrollViewer.SetHorizontalOffset (e.HorizontalOffset), когда происходит другое событие прокрутки. Ниже код в OuterGridView.xaml.cs на одном из определения обработчика (

private void Grid1Attached_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     if (e != null && !e.Handled) 
     { 
      if (e.HorizontalChange != 0.0) 
      { 
       grid2Control.Scroller.ScrollToHorizontalOffset(e.HorizontalOffset); 
      } 
      e.Handled = true; 
     } 
    } 
private void Grid2Attached_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     if (e != null && !e.Handled) 
     { 
      if (e.HorizontalChange != 0.0) 
      { 
       grid1Control.Scroller.ScrollToHorizontalOffset(e.HorizontalOffset); 
      } 
      e.Handled = true; 
     } 
    } 

Также убедитесь, что любое другое событие scroll_changed внутри внутренней сетки (если таковые имеются, например, если вы определяете TextBox с скроллер по умолчанию в одном из шаблонов данных столбца) имеет свой набор e.Handled в true, чтобы предотвратить обработку обработчиком внешней сетки (это произошло из-за поведения барботирования по умолчанию для маршрутизируемых событий). В качестве альтернативы вы можете добавить дополнительные данные, если проверка на e.OriginalSource или e.Source чтобы отфильтровать событие прокрутки, которое вы планируете обработать.

Смежные вопросы