[英]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.