wpf datagrid binding




Synchronisation des positions de défilement pour 2 DataGrids WPF (4)

Il y a un bon morceau de code pour faire ceci:

http://www.codeproject.com/KB/WPF/ScrollSynchronization.aspx

J'essaye de synchroniser la position horizontale de défilement de 2 contrôles de DataGrid de WPF .

Je suis abonné à l'événement ScrollChanged du premier DataGrid:

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

J'ai un second DataGrid:

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

Dans le gestionnaire d'événements, IScrollInfo.SetHorizontalOffset d'utiliser le IScrollInfo.SetHorizontalOffset , mais hélas, DataGrid n'expose pas IScrollInfo :

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

Y a-t-il un autre moyen d'accomplir cela? Ou y at-il un autre élément sur TargetGrid qui expose le IScrollInfo nécessaire pour réaliser la synchronisation des positions de défilement?

BTW, j'utilise des colonnes gelées , donc je ne peux pas envelopper les deux contrôles DataGrid avec ScrollViewers.


Nous avons rencontré le même problème lors de l'utilisation de la grille Infragistics car elle ne prenait pas (encore) en charge les colonnes gelées. Nous avions donc deux grilles côte-à-côte qui semblaient ne faire qu'un. La grille de gauche ne défile pas horizontalement mais la grille de droite le fait. Les colonnes gelées du pauvre.

Quoi qu'il en soit, nous avons fini par atteindre l'arbre visuel et sortir le ScrollViewer nous-mêmes. Après tout, nous savions qu'il était là - il n'était tout simplement pas exposé par le modèle d'objet. Vous pouvez utiliser une approche similaire si la grille WPF n'expose pas le ScrollViewer. Ou vous pourriez sous-classer la grille et ajouter la fonctionnalité dont vous avez besoin pour que cela fonctionne.

Intéressé à entendre pourquoi vous avez besoin de faire cela.


C'est une excellente solution. J'ai bien travaillé pour moi dans WPF.

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

Je viens de faire une référence à ScrollSynchronizer dll, ajouté une importation XML:

xmlns: scroll = "clr-namespace: ScrollSynchronizer"

alors juste ajouté ceci à mes deux datagrids et bobs votre oncle:

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

Vous pouvez tromper la grille de données pour exposer son ScrollViewer en tant que propriété publique pour chaque grille, par exemple lorsque le gestionnaire innerGridControl_ScrollChanged () est appelé lors de l'initialisation de la commande usercontrol. Pour l'exposer, vous pouvez créer votre grille dans un fichier xaml View, puis en composer deux dans une autre vue xaml. Le code ci-dessous est sur le innerGrid.xaml.cs par exemple:

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

sur OuterGridView.xaml mettre une définition de gestionnaire d'événements attaché:

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

puis accédez à cette méthode publique ScrollViewer.SetHorizontalOffset (e.HorizontalOffset) lorsqu'un autre événement de défilement se produit. Le code ci-dessous se trouve dans OuterGridView.xaml.cs sur l'une des définitions de gestionnaire (

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

Assurez-vous également que tout autre événement scroll_changed dans la grille interne (le cas échéant, par exemple si vous définissez un TextBox avec un scroller par défaut dans l'un des gabarits de colonne) a son e.Handled sur true pour empêcher le gestionnaire de la grille externe de le traiter. est arrivé en raison du comportement de bouillonnement par défaut de routedevents). Vous pouvez également ajouter des options supplémentaires si vous vérifiez sur e.OriginalSource ou e.Source pour filtrer l'événement de défilement que vous souhaitez traiter.





scroll