Ширины столбцов WPF DataGrid Sync

У меня есть два WPF Toolkit DataGrids, мне бы хотелось, чтобы при изменении размера первого столбца в первой сетке он изменил размер первого столбца во второй сетке. Я попытался связать ширину DataGridColumn во второй сетке с соответствующим столбцом в первой сетке, но она не работает. Я бы предпочел использовать все xaml, но я в порядке с использованием кода.

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

Я также пытался привязать к Width вместо ActualWidth, но не работает.

Любая помощь очень ценится.

Ответ 1

Ну, я не думаю, что это возможно, используя прямой XAML, но я все еще чувствую, что это нужно, потому что DataGridColumn происходит от DependencyObject. Однако я нашел способ сделать это программно. Я не в восторге от этого, но он работает:

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

Ответ 2

Вы можете использовать метод DataGrid LayoutUpdated для управления другими объектами относительно ширины столбцов.

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

Ответ 3

Я пробовал это:

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

Однако, похоже, что поскольку DataGridColumn не выводится из FrameworkElement, а вместо этого получается из DependencyObject, привязка таким образом недоступна.

Ответ 4

Если вы хотите связать свойство ширины столбца в XAML, в 2 DataGrid, вам нужно сделать следующее.

В первом DataGrid имени DataGridTextColumn:

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

Во втором DataGrid добавьте DiscreteObjectKeyFrame, указывающий на вышеупомянутый столбец в качестве ресурса, и используйте следующее свойство Binding to Width в DataGridTextColumn, которое вы хотите "связать":

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

Ответ 5

Я нашел решение этой проблемы и дополнительное крутое решение:-) Вы можете загрузить инструментарий WPF и получить код DataGrid. После того, как у вас есть код, все, что вам нужно сделать, это изменить класс DataGridColumn для наследования FrameworkElement вместо DependencyObject. Как только вы это сделаете - у вас осталась только одна проблема, DataContext столбца не будет инициализирован, так как столбец не является частью логического дерева, и это добавит его в логическое дерево. Вы можете сделать это следующим образом: Где OnColumnInitialization:       private void OnColumnInitialization (отправитель объекта, EventArgs e)       {
          AddLogicalChild (отправитель);       } Теперь, когда это часть логического дерева, у вас есть один и тот же контекст данных, и вы можете использовать привязку на Свойство Width. Если все привязаны к одной и той же ширине - у вас есть полная синхронизация ширины столбцов. Это сработало для меня:-) Гили