У меня есть два 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, но ни один из них не работает.
Любая помощь приветствуется.





Я пробовал это:
<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, но я все же считаю, что это должно быть, потому что 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);
}
@SoMoS - DataGridColumn.WidthProperty - это свойство зависимости. AddValueChanged - это метод расширения для свойства зависимости, аргументы, которые ему нужны, - это исходный объект и обработчик событий. Делегат, который вы видите в первых двух определениях, - это анонимный метод, обрабатывающий событие.
Я нашел решение этой проблемы и очень крутое решение :-)
Вы можете загрузить набор инструментов WPF и получить код DataGrid.
Когда у вас есть код, все, что вам нужно сделать, это изменить класс DataGridColumn, чтобы он наследовал FrameworkElement вместо DependencyObject.
Как только вы это сделаете - у вас останется только одна проблема: DataContext столбца не будет инициализирован, поскольку столбец не является частью логического дерева, добавление его в логическое дерево решит эту проблему.
Сделать это можно так:
Где OnColumnInitialization:
private void OnColumnInitialization (отправитель объекта, EventArgs e)
{
AddLogicalChild (отправитель);
}
Теперь, когда он является частью логического дерева, у вас есть тот же контекст данных, и вы можете использовать привязку к
Свойство ширины.
Если все привязаны к одной и той же ширине - у вас полная синхронизация ширины ваших столбцов.
Это сработало для меня :-)
Гили
Исправление ошибки в коде фреймворка мне не кажется «очень крутым решением». Это больше похоже на огромную боль.
Вы можете использовать метод DataGridLayoutUpdated для управления другими объектами относительно ширины столбца.
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;
}
Если вы хотите привязать свойство ширины столбца в XAML, в двух DataGrid вам необходимо сделать следующее.
В первом DataGrid назовите DataGridTextColumn:
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn x:Name = "Col1"/>
</DataGrid.Columns>
</DataGrid>
Во втором DataGrid добавьте DiscreteObjectKeyFrame, указывающий на вышеупомянутый столбец в качестве ресурса, и используйте следующее свойство Binding to 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>
Я быстро решил эту проблему, используя прикрепленное поведение, вдохновленное ответом Ахмеда выше.
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>
Вторая сетка данных, ширина заголовка и ячейки, теперь синхронизируется с шириной заголовка первой сетки.
Извините, но я не получил ваш код. Какие два первых определения? Методы? Они не похожи на метод, а параметры не имеют типа ...