WPF Datagrid 동기화 열 너비
-
03-07-2019 - |
문제
두 개의 WPF 툴킷이 있습니다 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
, 그러나 어느 쪽도 작동하지 않습니다.
모든 도움은 대단히 감사합니다.
해결책
글쎄요 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
S는 파생되지 않습니다 FrameworkElement
대신에서 파생됩니다 DependencyObject
, 이러한 방식으로 바인딩을 사용할 수 없습니다.
XAML에서 열 폭 속성을 바인딩하려면 2 DataGrid
다음을 수행 해야하는 것보다.
처음에는 DataGrid
이름을 지정하십시오 DataGridTextColumn
:
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn x:Name="Col1"/>
</DataGrid.Columns>
</DataGrid>
두 번째 DataGrid
~을 추가하다 DiscreteObjectKeyFrame
위에서 언급 한 열을 리소스로 가리키고 다음을 사용하십시오. Binding
에게 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>
위의 Ahmed Answer에서 영감을 얻은 첨부 된 동작을 사용하는 데 빠른 솔루션을 수행했습니다.
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>
두 번째 데이터 그라이드, 헤더 및 셀 폭은 이제 첫 번째 그리드 헤더 너비와 동기화됩니다.
이 문제에 대한 해결책과 추가 쿨 솔루션을 찾았습니다. :-) WPF 툴킷을 다운로드하여 Datagrid의 코드를 얻을 수 있습니다. 코드가 있으면 DataGridColumn 클래스를 변경하여 종속성 대신 FrameworkElement를 상속 받기 만하면됩니다. 일단 그렇게하면 - 한 가지 문제 만 남습니다. 열이 논리적 트리의 일부가 아니기 때문에 열의 데이터 컨텍스트는 초기화되지 않으므로 논리적 트리에 추가하면 이것을 해결합니다. 당신은 다음과 같이 할 수 있습니다.
AddLogicalChild (Sender); } 이제 논리적 트리의 일부이므로 동일한 데이터 컨텍스트를 가지고 있으며 너비 속성에 바인딩을 사용할 수 있습니다. 모두가 같은 너비에 묶인 경우 열의 너비와 완전히 동기화됩니다. 이것은 나를 위해 일했다 :-) 길리