Pregunta

Tengo dos WPF Toolkit DataGrids , me gustaría que cuando el usuario cambie el tamaño de la primera columna en la primera cuadrícula, cambie el tamaño de la primera columna en la segunda cuadrícula. He intentado vincular el ancho de DataGridColumn en la segunda cuadrícula a la columna apropiada en la primera cuadrícula, pero no funciona. Preferiría usar todo xaml, pero también estoy de acuerdo con usar el código que está detrás.

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

También intenté enlazar a Width en lugar de ActualWidth , pero ninguno funciona.

Cualquier ayuda es muy apreciada.

¿Fue útil?

Solución

Bueno, no creo que sea posible usar XAML directo, pero sigo pensando que debería hacerlo porque DataGridColumn se deriva de DependencyObject . Aunque encontré la manera de hacerlo programáticamente. No estoy emocionado por eso, pero funciona:

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

Otros consejos

Puede utilizar el método DataGrid LayoutUpdated para manipular otros objetos con respecto a los anchos de columna.

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

He intentado esto:

<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>
Sin embargo, parece que, dado que DataGridColumn no procede de FrameworkElement , sino que deriva de DependencyObject , el enlace de esta manera no está disponible .

Si desea vincular la propiedad Width de la columna en XAML, en 2 DataGrid es necesario hacer lo siguiente.

En el primer DataGrid nombre el DataGridTextColumn :

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

En el segundo DataGrid agregue un DiscreteObjectKeyFrame que apunta a la columna mencionada anteriormente como un recurso, y use el siguiente Binding para Ancho en el DataGridTextColumn que desea " enlace " ;:

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

Hice una solución rápida a esto al usar un comportamiento adjunto, Inspired by Ahmed responde arriba.

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>

Las segundas redes de datos, el encabezado y el ancho de la celda, ahora están sincronizadas con el primer ancho del encabezado de la cuadrícula.

Encontré una solución a este problema, y ??una solución extra genial :-) Puede descargar el kit de herramientas de WPF y obtener el código de DataGrid. Una vez que tenga el código, todo lo que tiene que hacer es cambiar la clase DataGridColumn para heredar FrameworkElement en lugar de DependencyObject. Una vez que lo haga, solo tendrá un problema, el DataContext de la columna no se inicializará, ya que la columna no forma parte del árbol lógico; Puedes hacerlo así: Donde está la OnColumnInitialization:         Vacío privado OnColumnInitialization (objeto remitente, EventArgs e)         {
            AddLogicalChild (remitente);         } Ahora que forma parte del árbol lógico, tiene el mismo contexto de datos y puede usar el enlace en el Propiedad de ancho. Si todos están vinculados al mismo ancho, tiene una sincronización completa del ancho de sus columnas. Esto funcionó para mí :-) Gili

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top