Search code examples
wpfheaderdatatemplategridviewcolumn

How to access the element within the DataTemplate of GridViewColumnHeader?


How can I get access to an element (TextBlock) within the DataTemplate of GridViewColumnHeader from the code???? I want to set focus on the column header.


Solution

  • Just any GridViewColumnHeader or one in particular? You can use this code

    List<GridViewColumnHeader> allGridViewColumnHeaders = GetVisualChildCollection<GridViewColumnHeader>(listView);
    foreach (GridViewColumnHeader columnHeader in allGridViewColumnHeaders)
    {
        TextBlock textBlock = GetVisualChild<TextBlock>(columnHeader);
        if (textBlock != null)
        {
    
        }
    }
    

    And the helper methods

    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);
            }
        }
    }
    
    private T GetVisualChild<T>(DependencyObject parent) where T : Visual
    {
        T child = default(T);
        int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < numVisuals; i++)
        {
            Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
            child = v as T;
            if (child == null)
            {
                child = GetVisualChild<T>(v);
            }
            if (child != null)
            {
                break;
            }
        }
        return child;
    }
    

    Update

    To make a GridViewColumnHeader get focus you can

    columnHeader.Focus();
    

    Depending on where you do this it might not work, then you can try

    EventHandler eventHandler = null;
    eventHandler = new EventHandler(delegate
    {
        listView.LayoutUpdated -= eventHandler;
        GridViewColumnHeader columnHeader = GetVisualChild<GridViewColumnHeader>(listView);
        columnHeader.Focus();
    });
    listView.LayoutUpdated += eventHandler;
    

    Also make sure that your GridViewColumnHeader has the following attributes

    <GridViewColumnHeader IsTabStop="True" Focusable="True">