[英]WPF: Binding Data Grid Header Width
我试图将一个数据网格的标头的宽度绑定到另一个数据网格的标头。
因此,我为父数据网格的每一行添加了一个数据网格。 现在,我尝试使用“父”标头的列控制子数据网格的列大小。
因此,在最后一列的标题模板中,我添加了一个仅具有列标题而没有行的数据网格。 在本专栏的单元模板中,我添加了另一个数据网格,没有标题,只有数据行。
当我调整headertemplate datagrid列标题的大小时,XAML中有什么方法可以调整celltemplate的datagrid列的大小。
阅读大量关于SO的答案,以及关于CodeProject等的一些帖子,但是我无法使其工作。 有可能吗?
XAML
<Grid>
<DataGrid x:Name="Test"
AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding AllAssets}"
CanUserResizeColumns="True">
<DataGrid.Resources>
<DataTemplate x:Key="NewKey2">
<DataGrid Name="dgC"
AutoGenerateColumns="False"
HeadersVisibility="None"
ItemsSource="{Binding months}"
CanUserResizeColumns="True">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Col1" Binding="{Binding value}" />
<DataGridTextColumn x:Name="Col2" Binding="{Binding MonthName}" />
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
<DataTemplate x:Key="NewKey3">
<StackPanel>
<Label HorizontalAlignment="Center">All Headers</Label>
<DataGrid Name="dgH">
<DataGrid.Columns>
<DataGridTextColumn Width="{Binding ElementName=Col1, Path=ActualWidth}" Header="Value" />
<DataGridTextColumn Width="{Binding ElementName=Col2, Path=ActualWidth}" Header="Month" />
<!--Error or no result on these attempts
<DataGridTextColumn Header="Month" Width="{Binding Source={x:Reference Col2}, Path=ActualWidth}"/>--><!--
<DataGridTextColumn >
<DataGridTextColumn.Header>
<TextBlock Width="{Binding Source={x:Reference Col1}, Path=ActualWidth}" >Value</TextBlock>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Header="Month" />-->
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding id}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn CellTemplate="{StaticResource NewKey2}"
HeaderTemplate="{StaticResource NewKey3}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
C#类数据例如:
namespace WpfApplication1
{
public class Assets
{
public List<Asset> AllAssets { get; set; }
public Assets()
{
AllAssets = new List<Asset>();
for (int i = 1; i < 3; i++)
{
Asset asset = new Asset();
asset.id = i;
asset.name = "asset " + i.ToString();
for (int x = 1; x < 3; x++)
{
MonthsData months = new MonthsData();
months.MonthName = "Month " + x.ToString();
months.value = x;
asset.months.Add(months);
}
AllAssets.Add(asset);
}
}
}
public class Asset
{
public int id { get; set; }
public string name { get; set; }
public List<MonthsData> months { get; set; }
public Asset()
{
months = new List<MonthsData>();
}
}
public class MonthsData
{
public string MonthName { get; set; }
public int value { get; set; }
}
}
假设您可以在ViewModel中定义几个属性
public class Assets : MVVM.ViewModel.ViewModelBase
{
public List<Asset> AllAssets { get; set; }
private double col1Width;
private double col2Width;
public double Col1Width
{
get { return col1Width; }
set { col1Width = value; OnPropertyChanged("Col1Width"); }
}
public double Col2Width
{
get { return col2Width; }
set { col2Width = value; OnPropertyChanged("Col2Width"); }
}
那么您将能够通过助手从XAML读取Load事件时的实际宽度
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
var dg = FindVisualChildByName<DataGrid>(Test, "dgC");
assets.Col1Width = dg.Columns[0].ActualWidth;
assets.Col2Width = dg.Columns[1].ActualWidth;
}
并将它们从网格的DataContext设置回XAML绑定
<DataGridTextColumn Header="Value" >
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Width" Value="{Binding ElementName=Test, Path=DataContext.Col1Width, UpdateSourceTrigger=PropertyChanged}"/>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Month" >
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Width" Value="{Binding ElementName=Test, Path=DataContext.Col2Width, UpdateSourceTrigger=PropertyChanged}"/>
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>
正如下面的注释中正确指出的那样,我们可以避免“仅与ViewModel中的View相关的属性”,并管理任意(但固定)数目的列,以使dgC和dgH的宽度相同(假设它们具有相同的宽度)列数)链接
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
var dgC = FindVisualChildByName<DataGrid>(Test, "dgC");
var dgH = FindVisualChildByName<DataGrid>(Test, "dgH");
for (int i = 0; i < dgC.Columns.Count; i++)
{
dgH.Columns[i].Width = dgC.Columns[i].ActualWidth;
}
}
在这种情况下,不再需要VM绑定
<DataGridTextColumn Header="Value" />
<DataGridTextColumn Header="Month" />
这比较复杂,因此,只有在严格要求时才继续操作。
让我们更改该实用程序,以便它将返回所有datagrid dgC(每行有一个dgC)
public static IEnumerable<T> FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
{
List<T> list = new List<T>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
string controlName = child.GetValue(Control.NameProperty) as string;
if (controlName == name)
{
list.Add(child as T);
}
else
{
IEnumerable<T> result = FindVisualChildByName<T>(child, name);
if (result != null)
list.AddRange(result);
}
}
return list;
}
现在我们将为实际的宽度变化定义一个依赖属性
private bool _columnWidthChanging;
private void ColumnWidthPropertyChanged(object sender, EventArgs e)
{
// listen for when the mouse is released
_columnWidthChanging = true;
if (sender != null)
Mouse.AddPreviewMouseUpHandler(this, BaseDataGrid_MouseLeftButtonUp);
}
void BaseDataGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_columnWidthChanging)
{
_columnWidthChanging = false;
var dgCs = FindVisualChildByName<DataGrid>(Test, "dgC");
var dgH = FindVisualChildByName<DataGrid>(Test, "dgH").First();
foreach (var dgC in dgCs)
{
for (int i = 0; i < dgC.Columns.Count; i++)
{
var column = dgH.Columns[i];
dgC.Columns[i].Width = column.ActualWidth;
}
}
}
}
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
var dgC = FindVisualChildByName<DataGrid>(Test, "dgC").First();
var dgH = FindVisualChildByName<DataGrid>(Test, "dgH").First();
for (int i = 0; i < dgC.Columns.Count; i++)
{
var column = dgC.Columns[i];
dgH.Columns[i].Width = column.ActualWidth;
PropertyDescriptor pd = DependencyPropertyDescriptor
.FromProperty(DataGridColumn.ActualWidthProperty,
typeof(DataGridColumn));
//Add a listener for this column's width
pd.AddValueChanged(dgH.Columns[i],
new EventHandler(ColumnWidthPropertyChanged));
}
您可以使用一个Grid
,并设置SharedSizeGroup
财产ColumnDefinition
。 这将“自动”调整Grid.IsSharedSizeScope
定义的列的Grid.IsSharedSizeScope
如果您想了解有关此内置功能的更多信息,可以在Google上进行搜索或查看: https : //wpf.2000things.com/tag/sharedsizegroup/
我采用了您的代码以使其正常工作。 我取代了DataGrid
页眉/细胞模板,用一Grid
为了使用
XAML
<Grid Grid.IsSharedSizeScope="True">
<DataGrid AutoGenerateColumns="False"
CanUserAddRows="False"
ItemsSource="{Binding AllAssets}"
CanUserResizeColumns="True">
<DataGrid.Resources>
<DataTemplate x:Key="NewKey2">
<ItemsControl ItemsSource="{Binding months}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding value}"
Margin="5" />
<TextBlock Text="{Binding MonthName}"
Margin="5"
Grid.Column="2" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
<DataTemplate x:Key="NewKey3">
<StackPanel>
<Label HorizontalAlignment="Center">All Headers</Label>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" />
<ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>
<TextBlock Text="Value"
Margin="5" />
<TextBlock Text="Month"
Margin="5"
Grid.Column="1" />
</Grid>
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Id">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding id}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Name"
Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn CellTemplate="{StaticResource NewKey2}"
HeaderTemplate="{StaticResource NewKey3}" />
</DataGrid.Columns>
</DataGrid>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.