【问题标题】:How to synchronize column widths between two nested datagrids?如何在两个嵌套数据网格之间同步列宽?
【发布时间】:2010-12-31 13:32:36
【问题描述】:

我有一个带有几列的 wpf 工具包数据网格,然后在行详细信息中我有另一个数据网格。基本上我正在模拟一个 treelistview 控件(例如:http://www.codeproject.com/KB/list/treelistview.aspx),但使用的是数据网格。

我想将行详细信息中数据网格的列宽与主父数据网格的列宽同步。

我尝试像这样定义一个子数据网格列:

<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”方法。 任何人都知道问题可能是什么?或者有什么其他建议?谢谢

【问题讨论】:

    标签: wpf .net-3.5 datagrid binding


    【解决方案1】:

    一种选择是使用 Grid 而不是 Datagrid。您可以在共享相同大小的各个列定义上使用 SharedSizeGroup 属性。

    【讨论】:

    【解决方案2】:

    使用此 Avalon(WPF 前)团队博客文章,我设法得到了一些有用的东西。我以为我也用 DataGrid 实现了它,但我搜索了我的代码,但一无所获。无论如何,如果你下定决心,你会想办法解决的,希望这会有所帮助。

    http://blogs.msdn.com/atc_avalon_team/archive/2006/03/01/541206.aspx

    【讨论】:

    • 谢谢,如果数据网格最终不能为我工作,它看起来很有帮助。
    【解决方案3】:

    我知道这是一个老问题(从 2010 年开始),但这是我解决相同问题的方法。本质上,我在创建它们时保留对所有嵌套 ListViews 的引用,在后面的代码中,然后在我的父“列”时更新它们的宽度(在我的情况下,使用网格创建的人造列,但同样的原则适用)宽度有变化。

    注意 - 在 XAML 中,我将 ListView_Loaded 指定为子(嵌套)列表视图的 Loaded 事件的处理程序。

    忽略我的父列更改事件是GridSplitter_DragDelta,这是因为我使用GridSplitter“伪造”了顶级标题行;在您的情况下,您将在自己的事件处理程序中获得要移动的列的宽度,然后使用 linq 语句“childViewColumns.ForEach((gvcc) => 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);
    
            }
    
    }
    

    【讨论】:

      【解决方案4】:

      好的,我已经完成了这项工作,但我对它并不完全满意。问题在于未正确检测到儿童。基本上,我在未连接的位置手动钻取了视觉树(使用 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;
                  }
              }
          }
      }
      

      【讨论】:

      • 请您也为您的 FindChild 方法提供一个实现吗?
      猜你喜欢
      • 2021-04-08
      • 1970-01-01
      • 2011-04-04
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 2011-11-18
      • 2020-07-21
      • 1970-01-01
      相关资源
      最近更新 更多