質問

2つのWPF Toolkit DataGrids があるので、ユーザーが最初のグリッドの最初の列のサイズを変更すると、2番目のグリッドの最初の列のサイズが変更されるようにします。 2番目のグリッドの 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>

ActualWidth ではなく Width にバインドしようとしましたが、どちらも機能しません。

ご協力ありがとうございます。

役に立ちましたか?

解決

まあ、ストレート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);
}

他のヒント

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

これを試しました:

<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 から派生するため、この方法でバインドすることはできません。

XAMLで列のWidthプロパティをバインドする場合、2つの DataGrid で次の操作を行う必要があります。

最初の DataGrid の名前は DataGridTextColumn

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

2番目の DataGrid で、リソースとして上記の列を指す DiscreteObjectKeyFrame を追加し、次の Binding に使用します&quot;リンク&quot;する 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>

添付のビヘイビアを使用することで、上記のアーメドの回答に触発されて、これに対する簡単な解決策を実行しました。

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>

2番目のDataGrid、ヘッダーとセルの幅は、最初のグリッドヘッダーの幅と同期します。

この問題の解決策と、さらにクールな解決策を見つけました:-) WPFツールキットをダウンロードして、DataGridのコードを取得できます。 コードを取得したら、DataGridColumnクラスを変更して、DependencyObjectではなくFrameworkElementを継承するだけです。 これを行うと、列は論理ツリーの一部ではないため、列のDataContextは初期化されず、論理ツリーに追加するだけでこれが解決されます。 次のようにできます: OnColumnInitializationは次のとおりです。         private void OnColumnInitialization(オブジェクト送信者、EventArgs e)         {
            AddLogicalChild(sender);         } これは論理ツリーの一部であるため、同じデータコンテキストがあり、バインディングを使用できます 幅プロパティ。 すべてが同じ幅にバインドされている場合-列の幅が完全に同期されます。 これは私のために働いた:-) ギリ

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top