Pergunta

Eu tenho dois WPF Toolkit DataGrids, Eu gostaria que, quando o usuário redimensione a primeira coluna na primeira grade, ele redimensione a primeira coluna na segunda grade. Eu tentei amarrar a largura do DataGridColumn Na segunda grade da coluna apropriada na primeira grade, mas não funciona. Eu prefiro usar todo o XAML, mas estou bem em usar o código por trás também.

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

Eu também tentei vincular -se a Width ao invés de ActualWidth, mas nenhum deles funciona.

Qualquer ajuda é muito apreciada.

Foi útil?

Solução

Bem, eu não acho que seja possível usar xaml reto, mas ainda sinto que deveria porque DataGridColumn deriva de DependencyObject. Eu encontrei uma maneira de fazer isso programaticamente. Não estou emocionado com isso, mas 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);
}

Outras dicas

Você pode usar o DataGrid LayoutUpdated Método para manipular outros objetos em relação às larguras da coluna.

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

Eu tentei o seguinte:

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

No entanto, parece que desde DataGridColumns não deriva de FrameworkElement mas em vez de derivar de DependencyObject, vinculativo dessa maneira não está disponível.

Se você deseja vincular a propriedade de largura da coluna em xaml, em 2 DataGridSão do que você tem que fazer o seguinte.

Em primeiro DataGrid Nomeie o DataGridTextColumn:

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

No segundo DataGrid Adicione a DiscreteObjectKeyFrame apontando para a coluna acima mencionada como um recurso e use o seguinte Binding para Width propriedade no DataGridTextColumn você quer "link":

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

Fiz uma solução rápida para usar um comportamento anexado, inspirado na resposta Ahmed acima.

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>

O segundo datagrids, cabeçalho e largura da célula, agora é sincronizado com a primeira largura do cabeçalho da grade.

Encontrei uma solução para esse problema e uma solução extra legal :-) Você pode baixar o WPF Toolkit e obter o código do DataGrid. Depois de ter o código, tudo o que você precisa fazer é alterar a classe DataGridColumn para herdar a estrutura do Framework em vez de dependencyObject. Depois de fazê -lo - você fica com apenas um problema, o datacontext da coluna não seria inicializado, pois a coluna não faz parte da árvore lógica, adicionando -a à árvore lógica resolveria isso. Você pode fazer assim: onde a oncolumnitialization é: private vazio oncolumnitialization (remetente de objeto, EventArgs e) {
AddLogicalChild (remetente); } Agora que faz parte da árvore lógica, você tem o mesmo contexto de dados e pode usar a ligação na propriedade de largura. Se todos estiverem vinculados à mesma largura - você terá uma sincronização completa da largura das suas colunas. Isso funcionou para mim :-) Gili

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top