Question

J'ai deux WPF Toolkit DataGrids . J'aimerais que, lorsque l'utilisateur redimensionne la première colonne de la première grille, il redimensionne la première colonne de la seconde. J'ai essayé de lier la largeur de DataGridColumn de la deuxième grille à la colonne appropriée de la première grille, mais cela ne fonctionne pas. Je préférerais utiliser tout le xaml, mais je peux aussi utiliser du code derrière.

<tk:DataGrid Width="100" Height="100">
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn x:Name="Column1" Width="50"/>
    </tk:DataGrid.Columns>
</tk:DataGrid>
<tk:DataGrid Width="100" Height="100">
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn x:Name="Column1Copy" Width="{Binding Path=ActualWidth, ElementName=Column1}"/>
    </tk:DataGrid.Columns>
</tk:DataGrid>

J'ai également essayé de faire la liaison à Width au lieu de ActualWidth , mais aucun des deux ne fonctionne.

Toute aide est grandement appréciée.

Était-ce utile?

La solution

Eh bien, je ne pense pas que ce soit possible d’utiliser du XAML pur, mais j’ai le sentiment que c’est le cas, car DataGridColumn provient de DependencyObject . J'ai cependant trouvé un moyen de le faire par programme. Je ne suis pas ravi à ce sujet, mais cela fonctionne:

DataGridColumn.WidthProperty.AddValueChanged(upperCol, delegate
{
    if (changing) return;
    changing = true;
    mainCol.Width = upperCol.Width;
    changing = false;
});
DataGridColumn.WidthProperty.AddValueChanged(mainCol, delegate 
{ 
    if (changing) return;
    changing = true;
    upperCol.Width = mainCol.Width; 
    changing = false; 
});

public static void AddValueChanged(this DependencyProperty property, object sourceObject, EventHandler handler)
{
    DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(property, property.OwnerType);
    dpd.AddValueChanged(sourceObject, handler);
}

Autres conseils

Vous pouvez utiliser la méthode DataGrid LayoutUpdated pour manipuler d'autres objets concernant les largeurs de colonne.

private void dataGrid1_LayoutUpdated(object sender, EventArgs e)
{
    for(int i = 0 ; i < dataGrid1.Columns.Count && i < dataGrid2.Columns.Count ; ++i)
        dataGrid2.Columns[i].Width = dataGrid1.Columns[i].ActualWidth;
}

J'ai essayé ceci:

<tk:DataGrid Width="100" Height="100" x:Name="Grid1" Grid.Column="0">
   <tk:DataGrid.Columns>
      <tk:DataGridTextColumn x:Name="Column1" Width="50"/>
   </tk:DataGrid.Columns>
</tk:DataGrid>
<tk:DataGrid Width="100" Height="100" x:Name="Grid2" Grid.Column="1">
   <tk:DataGrid.Columns>
     <tk:DataGridTextColumn x:Name="Column1Copy" Width="{Binding Mode=TwoWay, Path=Columns[0].ActualWidth, ElementName=Grid1}"/>
     </tk:DataGrid.Columns>
</tk:DataGrid>

Cependant, il semble que puisque les DataGridColumn ne dérivent pas de FrameworkElement , mais dérivent plutôt de DependencyObject , la liaison de cette manière n'est pas disponible. .

Si vous souhaitez lier la propriété Width de la colonne en XAML, dans 2 DataGrid , procédez comme suit:

Dans le premier DataGrid , nommez le DataGridTextColumn :

<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="Col1"/>
    </DataGrid.Columns>
</DataGrid>

Dans le deuxième DataGrid , ajoutez un DiscreteObjectKeyFrame pointant sur la colonne mentionnée ci-dessus en tant que ressource et utilisez le Binding suivant pour Largeur de la propriété DataGridTextColumn que vous souhaitez "lier":

<DataGrid>
    <DataGrid.Resources>
        <DiscreteObjectKeyFrame x:Key="proxyCol1" Value="{Binding ElementName=Col1}"/>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn  Width="{Binding Path=Value.Width, Mode=TwoWay, Source={StaticResource proxyCol1}}"/>
    </DataGrid.Columns>
</DataGrid>

J'ai résolu rapidement le problème en utilisant un comportement attaché. Inspiré par Ahmed, répondez ci-dessus.

public class DataGridWidthSyncronizerBehavior
{
    public static readonly DependencyProperty SyncronizeWidthWithProperty =
        DependencyProperty.RegisterAttached("SyncronizeWidthWith",
            typeof(DataGrid),
            typeof(DataGridWidthSyncronizerBehavior),
            new UIPropertyMetadata(null, SyncronizeWidthWithChanged));

    public static void SetSyncronizeWidthWith(DependencyObject target, DataGrid value)
    {
        target.SetValue(SyncronizeWidthWithProperty, value);
    }

    public static DataGrid GetSyncronizeWidthWith(DependencyObject target)
    {
        return (DataGrid)target.GetValue(SyncronizeWidthWithProperty);
    }

    private static void SyncronizeWidthWithChanged(DependencyObject obj, DependencyPropertyChangedEventArgs dpargs)
    {
        if (!(obj is DataGrid sourceDataGrid))
            return;

        if (!(sourceDataGrid.GetValue(SyncronizeWidthWithProperty) is DataGrid targetDataGrid))
            return;

        void Handler(object sender, EventArgs e)
        {
            for (var i = 0; i < sourceDataGrid.Columns.Count && i < targetDataGrid.Columns.Count; ++i)
                targetDataGrid.Columns[i].Width = sourceDataGrid.Columns[i].ActualWidth;
        }

        sourceDataGrid.LayoutUpdated -= Handler;
        sourceDataGrid.LayoutUpdated += Handler;
    }
}

XAML:

<DataGrid local:DataGridWidthSyncronizerBehavior.SyncronizeWidthWith="{Binding ElementName=SyncronizedHeaderGrid}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Header 1" 
                            Binding="{Binding Item1}" />
        <DataGridTextColumn Header="Header 2" 
                            Binding="{Binding Item2}"/>
        <DataGridTextColumn Header="Header 3" 
                            Binding="{Binding Item3}"/>
    </DataGrid.Columns>
</DataGrid>

<DataGrid x:Name="SyncronizedHeaderGrid">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Header 1" 
                            Binding="{Binding Item1}" />
        <DataGridTextColumn Header="Header 2" 
                            Binding="{Binding Item2}"/>
        <DataGridTextColumn Header="Header 3" 
                            Binding="{Binding Item3}"/>
    </DataGrid.Columns>
</DataGrid>

La deuxième grille de données, en-tête et largeur de cellule, est maintenant synchronisée avec la première largeur d'en-tête de grille.

J'ai trouvé une solution à ce problème et une solution très cool :-) Vous pouvez télécharger le toolkit WPF et obtenir le code du DataGrid. Une fois que vous avez le code, tout ce que vous avez à faire est de changer la classe DataGridColumn pour qu'elle hérite de FrameworkElement au lieu de DependencyObject. Une fois que vous le faites - il ne vous reste qu'un problème, le DataContext de la colonne ne sera pas initialisé car la colonne ne fait pas partie de l'arborescence logique, son ajout à l'arborescence logique résoudrait ce problème. Vous pouvez le faire comme ça: Où l'initialisation OnColumn est:         void privé OnColumnInitialization (expéditeur d'objet, EventArgs e)         {
            AddLogicalChild (expéditeur);         } Maintenant qu’il fait partie de l’arborescence logique, vous avez le même contexte de données et vous pouvez utiliser la liaison sur le disque. Propriété de largeur. Si tous sont liés à la même largeur, vous obtenez une synchronisation complète de la largeur de vos colonnes. Cela a fonctionné pour moi :-) Gili

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top