2008-11-16 18 views
6

Ich versuche zu synchronisieren die horizontale Scroll-Position von 2 WPF Datagrid Kontrollen.Synchronisieren scroll Positionen für 2 WPF Datagrids

ich zum melde mich an ScrollChanged Ereignis des ersten Datagrid:

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

ich ein zweites Datagrid haben:

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

im Ereignishandler ich versuchte, die IScrollInfo.SetHorizontalOffset zu verwenden, aber achtet DataGrid nicht IScrollInfo:

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

Gibt es einen anderen Weg, dies zu erreichen? Oder gibt es ein anderes Element auf TargetGrid, das die erforderlichen IScrollInfo verfügbar macht, um die Synchronisation der Scroll-Positionen zu erreichen?

BTW, ich bin mit eingefrorenen Spalten, so kann ich nicht beide DataGrid-Steuerelemente mit ScrollViewers umbrechen.

Antwort

3

Gemäß der Microsoft-Produktgruppe ist es empfehlenswert, den visuellen Baum zu durchlaufen, um den ScrollViewer zu finden, wie z. B. explained in their answer on Codeplex.

+0

Ja. Das gleiche habe ich in der Vergangenheit auch schon gemacht. Es scheint so, als müssten wir uns auf diese Weise nicht durch den visuellen Baum hacken. Nur ein weiterer Weg, WPF ist rau an den Rändern. – PeterAllenWebb

+2

Seien Sie vorsichtig, wenn der Benutzer visuelle Themen ändert - Kontrollen erhalten dann neue Vorlagen (= neue visuelle Bäume) und Sie werden einen Verweis auf einen falschen Scrollviewer haben. Sie sollten in OnApplyTemplate reagieren und den tatsächlichen ScrollViewer jedes Mal nachschlagen, wenn er aufgerufen wird. Siehe http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.onapplytemplate.aspx –

1

Wir hatten das gleiche Problem bei der Verwendung der Infragistics Grid, weil es nicht (immer noch nicht) unterstützt gefrorene Spalten. Wir hatten also zwei nebeneinander liegende Gitter, die so aussehen sollten. Das Gitter auf der linken Seite scrollt nicht horizontal, sondern das Gitter auf der rechten Seite. Die gefrorenen Säulen des armen Mannes.

Wie auch immer, wir landeten nur in den visuellen Baum und ziehen die ScrollViewer selbst aus. Schließlich wussten wir, dass es da war - es wurde einfach nicht vom Objektmodell entlarvt. Sie können einen ähnlichen Ansatz verwenden, wenn das WPF-Raster den ScrollViewer nicht verfügbar macht. Oder Sie können das Gitter unterklassifizieren und die Funktionalität hinzufügen, die Sie benötigen, um dies zu erreichen.

Interessiert zu hören, warum Sie dies tun müssen.

+0

Ich habe eine Quelle für das WPF Toolkit DataGrid von Codeplex, also könnte ich es finden und enthüllen (nicht meine bevorzugte Methode). Ich bin stac king 2 grids, um den gefrorenen Scheibeneffekt zu erhalten (ala Excel). –

0

Dies ist eine großartige Lösung. Hat in WPF gut funktioniert.

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

Ich habe gerade einen Verweis auf ScrollSynchronizer dll, hinzugefügt, um einen XML-Import:

xmlns: scroll = "clr-namespace: ScrollSynchronizer"

dann hat soeben dies sowohl meine Datagrids und Bobs Ihr Onkel:

1

Sie können Trick das DataGrid, um seinen ScrollViewer als öffentliche Eigenschaft für jedes Raster zu offenbaren, wenn für Beispielhandler 'innerGridControl_ScrollChanged()', der während der Initialisierung der Benutzersteuerung aufgerufen wird. Um es freizulegen, können Sie Ihr Raster in einer XAML-View-Datei erstellen und dann zwei davon in einer anderen XAML-View erstellen. Below-Code ist auf den innerGrid.xaml.cs zum Beispiel:

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; 
     } 
    } 

auf OuterGridView.xaml setzen ein Event-Handler-Definition angehängt:

<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> 

dann Zugriff auf das öffentliche ScrollViewer.SetHorizontalOffset (e.HorizontalOffset) Methode, wenn ein anderes Scroll-Ereignis auftritt. Below-Code ist in dem OuterGridView.xaml.cs auf einem der Handler Definition (

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; 
     } 
    } 

Auch stellen Sie sicher, anderes scroll_changed Ereignis innerhalb des inneren Gitters (falls vorhanden, zum Beispiel, wenn Sie einen Text mit Standard scroller definieren (in einer der Spalten-Datenschablonen), hat e.Handled auf true gesetzt, um zu verhindern, dass der äußere Grid-Handler sie verarbeitet (dies passierte aufgrund des Standard-Bubbling-Verhaltens von routedevents). Alternativ können Sie zusätzliche setzen, wenn Sie e.OriginalSource oder e.Source überprüfen um das Scroll-Ereignis zu filtern, das Sie bearbeiten möchten

Verwandte Themen