【问题标题】:How to get DataGridColumnHeader from DataGridColumn?如何从 DataGridColumn 获取 DataGridColumnHeader?
【发布时间】:2011-05-01 03:41:44
【问题描述】:

我的代码如下:

 void mainDataContextObj_CutSelectedColumnEvent(string columnId)
    {
        IList<DataGridColumn> columns = dg.Columns;

        for(int i=2; i<dg.Columns.Count; i++)
        {
            DataGridColumnHeader headerObj = dg.Columns[i].Header as DataGridColumnHeader;

             //This always returns headerObj as null!!!

        }
    }

我需要来自专栏的DataGridColumnHeader。我哪里错了?

【问题讨论】:

    标签: wpf datagrid header datagridcolumn


    【解决方案1】:

    DataGridColumn 的 Header 对象实际上是该列的可见标题,无论您将其设置为什么。 DataGridColumn 不是可视化树的一部分,因此无法直接访问它的 DataGridColumnHeader(我们甚至无法确定它是否存在)。但是你可以做这样的事情来尝试访问它

    DataGridColumnHeader headerObj = GetColumnHeaderFromColumn(column);
    
    private DataGridColumnHeader GetColumnHeaderFromColumn(DataGridColumn column)
    {
        // dataGrid is the name of your DataGrid. In this case Name="dataGrid"
        List<DataGridColumnHeader> columnHeaders = GetVisualChildCollection<DataGridColumnHeader>(dataGrid);
        foreach (DataGridColumnHeader columnHeader in columnHeaders)
        {
            if (columnHeader.Column == column)
            {
                return columnHeader;
            }
        }
        return null;
    }
    
    public List<T> GetVisualChildCollection<T>(object parent) where T : Visual
    {
        List<T> visualCollection = new List<T>();
        GetVisualChildCollection(parent as DependencyObject, visualCollection);
        return visualCollection;
    }
    
    private void GetVisualChildCollection<T>(DependencyObject parent, List<T> visualCollection) where T : Visual
    {
        int count = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < count; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            if (child is T)
            {
                visualCollection.Add(child as T);
            }
            else if (child != null)
            {
                GetVisualChildCollection(child, visualCollection);
            }
        }
    }
    

    【讨论】:

    • 它在AutoGeneratedColumns 事件中不可用(它还找不到任何标题,它返回null)。之后确实有效。那么这些标头究竟是什么时候创建的呢?!
    • @Vibo:试试 DataGrid 的 Loaded 事件
    • 谢谢!我确实试过了,但缺点是它只是在一开始就被触发了,但是如果你通过将一些其他数据源分配给它的DataContext 来重新生成 DataGrid 的列,它就不会再次被触发。我尝试了所有可能的事件,我发现 LayoutUpdated 可以解决问题!
    • @Vibo: 否则你可以使用DataGrid的ItemContainerGenerator.StatusChanged事件并将状态与事件处理程序中的ContainersGenerated进行比较
    • 很高兴知道,谢谢。由LayoutUpdated 实现它实际上有点小技巧,因为这个事件经常被触发。管道胶带样式,我只是使用了ignoreLayoutUpdated bool,在应用程序的那些部分中将其设置为false,它实际上对标题做了一些事情,因此需要照顾它们,并在退出之前重置为true事件。
    【解决方案2】:

    虽然Fredrik's answer 提供了一种重构方法,其中包含可能在代码的其他部分重用的附加方法,但我更喜欢将他的方法合并到一个方法中。也可能会有一些小的性能提升,因为它可以在找到标头后立即结束搜索,并且不需要继续搜索可视树中的所有子节点(这在大多数情况下很可能可以忽略不计)。

    private DataGridColumnHeader GetHeader(DataGridColumn column, DependencyObject reference)
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(reference); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(reference, i);
    
            DataGridColumnHeader colHeader = child as DataGridColumnHeader;
            if ((colHeader != null) && (colHeader.Column == column))
            {
                return colHeader;
            }
    
            colHeader = GetHeader(column, child);
            if (colHeader != null)
            {
                return colHeader;
            }
        }
    
        return null;
    }
    

    它是这样使用的:

    DataGridColumnHeader colHeader = GetHeader(column, myDataGrid);
    if (colHeader == null) { /* Not found */ }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 2011-04-01
      • 2018-10-26
      • 2020-01-24
      • 2013-09-16
      • 1970-01-01
      相关资源
      最近更新 更多