Как получить DataGridColumnHeader из DataGridColumn?

Мой код выглядит следующим образом:

 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 из колонки. Где я ошибаюсь?


person GuruC    schedule 27.10.2010    source источник


Ответы (2)


Объект Header DataGridColumn на самом деле является видимым заголовком этого столбца, каким бы он ни был. 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);
        }
    }
}
person Fredrik Hedblad    schedule 27.10.2010
comment
Он недоступен в событии AutoGeneratedColumns (пока не может найти заголовки, возвращает ноль). Это работает потом. Так когда именно создаются эти заголовки?! - person Konrad Morawski; 04.08.2011
comment
@Vibo: попробуйте событие Loaded для DataGrid - person Fredrik Hedblad; 04.08.2011
comment
Спасибо! Я действительно пытался это сделать, но недостатком было то, что он запускался только в начале, но если вы регенерировали столбцы DataGrid, назначив какой-либо другой источник данных его DataContext, он больше не запускался. Я перепробовал все возможные события и обнаружил, что LayoutUpdated помогает! - person Konrad Morawski; 04.08.2011
comment
@Vibo: в противном случае вы можете использовать событие ItemContainerGenerator.StatusChanged DataGrid и сравнить статус с ContainersGenerated в обработчике событий. - person Fredrik Hedblad; 04.08.2011
comment
Полезно знать, спасибо. Реализация его с помощью LayoutUpdated на самом деле была немного хаком, потому что это событие запускается довольно часто. В стиле клейкой ленты я просто использовал ignoreLayoutUpdated bool, установив для него значение false в тех частях приложения, где он действительно что-то делает с заголовками, поэтому о них нужно позаботиться, и сбросив значение true перед выходом из события. - person Konrad Morawski; 04.08.2011
comment
Знаете ли вы, есть ли способ сделать это в Silverlight? DataGridColumnHeader не имеет свойства Column для сравнения. - person Tevin; 13.06.2012

Хотя ответ Фредрика предлагает рефакторинговый подход с дополнительным методом, который потенциально можно повторно использовать в других частях кода, я предпочел объединить его методы в один единственный метод. Также может быть небольшой выигрыш в производительности, потому что он может завершить поиск, как только найдет заголовок, и ему не нужно продолжать поиск по всем дочерним элементам в визуальном дереве (в большинстве случаев это, скорее всего, незначительно).

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 */ }
person Ben    schedule 08.06.2014