Ширина столбца синхронизации WPF DataGrid - PullRequest
12 голосов
/ 05 января 2009

У меня есть два 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, но ни одна из них не работает.

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

Ответы [ 6 ]

13 голосов
/ 12 января 2009

Ну, я не думаю, что это возможно, используя прямой 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);
}
6 голосов
/ 27 ноября 2011

Вы можете использовать метод 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;
}
1 голос
/ 21 декабря 2017

Если вы хотите связать свойство Width столбца в 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>
1 голос
/ 06 января 2009

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

<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 s не являются производными от FrameworkElement, а вместо этого происходят от DependencyObject, привязка таким способом недоступна.

0 голосов
/ 08 августа 2018

Я быстро решил проблему с помощью прикрепленного поведения, вдохновленного ответом Ахмеда выше.

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>

Second DataGrids, ширина заголовка и ячейки теперь синхронизируются с шириной заголовка первой сетки.

0 голосов
/ 17 июня 2011

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

...