Larguras da coluna de sincronização do datagrid wpf
-
03-07-2019 - |
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.
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 DataGridColumn
s 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 DataGrid
Sã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