我有一个带有几列的wpf工具箱数据网格,然后在行详细信息中我有另一个数据网格。基本上我正在模拟treelistview控件(例如:http://www.codeproject.com/KB/list/treelistview.aspx)但使用datagrids。
我想将行详细信息中datagrid的列宽与主父数据网格的列宽同步。
我尝试像这样定义子数据网格列:
<toolkit:DataGridTextColumn Binding="{Binding Path=Name}" Width="{Binding ElementName=mainDataGrid, Path=Columns[0].ActualWidth}" />
这不起作用(即使有一些变体,如Mode = OneWay)。
编辑:
好的,我放弃让绑定工作。试用代码...... 现在,由于DataGrid不会触发更改列宽的事件,因此我自己创建了:
PropertyDescriptor pd = DependencyPropertyDescriptor.FromProperty(DataGridColumn.WidthProperty, typeof(DataGridColumn));
pd.AddValueChanged(testColumn, new EventHandler(mainDataGrid_WidthPropertyChanged));
private void mainDataGrid_WidthPropertyChanged(object sender, EventArgs e)
{
// this works fine, but how do I find my templated child datagrid?
}
该事件似乎正确触发,但我似乎无法找到我的模板化数据网格。每行都有一个行详细信息部分,但可以隐藏部分或全部。但即使我的行详细信息可见,我也找不到对它的引用(总是为空)。
DataGrid dg = mainDataGrid.FindChild(null, typeof(DataGrid)) as DataGridRow; // dg always null
这是我使用的'FindChild'方法。 谁知道问题可能是什么?还是其他任何建议?感谢
答案 0 :(得分:1)
一种选择是使用Grid而不是Datagrid。您可以在共享大小的各个列定义上使用SharedSizeGroup属性。
答案 1 :(得分:1)
使用这个Avalon(pre WPF)团队博客文章,我设法得到了一些有用的东西。我以为我已经用DataGrid实现了它,我搜索了我的代码并且没有提出任何结果。无论如何,如果你确定你会弄清楚,希望这会有所帮助。
http://blogs.msdn.com/atc_avalon_team/archive/2006/03/01/541206.aspx
答案 2 :(得分:0)
好的,我已经完成了这项工作,但我并不完全满意。问题是孩子没有被正确检测到。基本上我在未连接的位置手动钻取可视树(使用Mole来帮助我)。如果视觉树不同,这可能对其他人不起作用,但这是一个普遍的想法。这是我所做的粗略版本,但我仍然在查看它究竟发生了什么:
public MyWindow()
{
InitializeComponent();
PropertyDescriptor pd = DependencyPropertyDescriptor.FromProperty(DataGridColumn.WidthProperty, typeof(DataGridColumn));
pd.AddValueChanged(testColumn, new EventHandler(dgMain_WidthPropertyChanged));
// do the same for all columns
}
private void dgMain_WidthPropertyChanged(object sender, EventArgs e)
{
SyncColumnWidths();
}
private void SyncColumnWidths() // put all this in a try..catch too
{
ScrollContentPresenter scp = dgMain.FindChild(null, typeof(ScrollContentPresenter)) as ScrollContentPresenter;
ItemsPresenter ip = scp.Content as ItemsPresenter;
DataGridRowsPresenter dgrp = ip.FindChild(null, typeof(DataGridRowsPresenter)) as DataGridRowsPresenter;
foreach (DataGridRow dgr in dgrp.Children)
{
if (dgr.DetailsVisibility == Visibility.Visible)
{
DataGrid dg = dgr.FindChild(null, typeof(DataGrid)) as DataGrid; // child datagrid
if (dg != null)
{
for (int i = 0; i < dgMain.Columns.Count; i++)
dg.Columns[i].Width = dgMain.Columns[i].ActualWidth;
}
}
}
}
答案 3 :(得分:0)
我知道这是一个老问题(从2010年开始),但这是我如何解决同样的问题。本质上,我在后面的代码中创建了对所有嵌套ListView的引用,然后在我的父“列”(在我的例子中,使用网格创建的虚拟列,但同样的原则适用时)更新它们的宽度宽度有变化。
注意 - 在XAML中,我将ListView_Loaded指定为子(嵌套)列表视图的Loaded事件的处理程序。
忽略我的父列更改事件是GridSplitter_DragDelta的事实,这是因为我使用GridSplitters“伪造”顶级标题行;在你的情况下,你将获得在你自己的事件处理程序中移动的列的宽度,然后使用linq语句“childViewColumns.ForEach((gvcc)=&gt; gvcc [index] .Width”等分配它。
公共部分类SomeThing:UserControl
private List<GridViewColumnCollection> childViewColumns = new List<GridViewColumnCollection>();
private void ListView_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
GridView gv = ((ListView)sender).View as GridView;
childViewColumns.Add(gv.Columns);
}
private void GridSplitter_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
GridSplitter gs = sender as GridSplitter;
Grid g = gs.Parent as Grid;
int index = Grid.GetColumn(gs);
double w = g.ColumnDefinitions[index].Width.Value;
childViewColumns.ForEach((gvcc) => gvcc[index].Width = w);
}
}