13

我有两个 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,但都不起作用。

任何帮助是极大的赞赏。

4

6 回答 6

14

好吧,我认为直接使用 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);
}
于 2009-01-12T16:58:05.820 回答
6

您可以使用该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;
}
于 2011-11-27T04:10:16.753 回答
2

受上述艾哈迈德回答的启发,我使用附加行为快速解决了这个问题。

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>

第二个 DataGrids,标题和单元格宽度,现在与第一个网格标题宽度同步。

于 2018-08-08T10:42:25.330 回答
1

我试过这个:

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

但是,看起来由于DataGridColumns 不是从 s 派生FrameworkElement而是从 s 派生的DependencyObject,因此这种方式的绑定不可用。

于 2009-01-05T23:19:36.170 回答
1

如果要在 XAML 中绑定列 Width 属性,DataGrid则必须在 2 中执行以下操作。

DataGrid名字中DataGridTextColumn

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

在第二个中DataGrid添加一个DiscreteObjectKeyFrame指向上述列作为资源,并使用以下属性对Binding您想要“链接”:WidthDataGridTextColumn

<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>
于 2017-12-21T08:55:18.817 回答
-2

我找到了这个问题的解决方案,以及一个非常酷的解决方案 :-) 您可以下载 WPF 工具包并获取 DataGrid 的代码。获得代码后,您只需将 DataGridColumn 类更改为继承 FrameworkElement 而不是 DependencyObject。一旦你这样做了 - 你只剩下一个问题,列的 DataContext 不会被初始化,因为列不是逻辑树的一部分,将它添加到逻辑树将解决这个问题。你可以这样做: OnColumnInitialization 在哪里: private void OnColumnInitialization(object sender, EventArgs e) {
AddLogicalChild(发件人);现在它是逻辑树的一部分,您拥有相同的数据上下文,您可以在 Width 属性上使用绑定。如果所有都绑定到相同的宽度 - 你有你的列的宽度的完整同步。这对我有用:-)吉利

于 2011-06-16T23:12:57.567 回答