2

Within my Windows.Resources I have the following column defined:

    <DataGridTextColumn x:Key="CustomColumn" x:Shared="False">
        <DataGridTextColumn.Header>
            <StackPanel>
                <Label Padding="0" Name="labelA"/>
                <Separator HorizontalAlignment="Stretch"/>
                <Label Padding="0" Name="labelB"/>
            </StackPanel>
        </DataGridTextColumn.Header>
    </DataGridTextColumn>

I have an event that gets fired from my ViewModel and adds the following "CustomColumn" to my DataGrid:

            var column = FindResource("CustomColumn") as DataGridTextColumn;
            var label = FindName("labelA") as Label;
            label.Content = string.Format("A {0}", i);
            DataGrid1.Columns.Add(column); 

The question is, how would I change the content of the two labels inside the CustomColumn header? I above code fails because it is unable to find "labelA". (adding the column works, but I also need to set these labels). My guess is, I need to find it through the VisualTree -- but I want to make sure I'm not doing anything else wrong.

Thanks for the help.

1 Answer 1

2

I created some Visual Tree helpers that I use all the time to find objects in the Visual Tree

For example, you can find a Label named "LabelA" with this:

VisualTreeHelpers.FindChild<Label>(column, "LabelA");

Here's the FindChild method in case the above link doesn't work

using System.Windows;
using System.Windows.Media;

namespace MyNamespace
{
    public class VisualTreeHelpers
    {
        /// <summary>
        /// Looks for a child control within a parent by name
        /// </summary>
        public static T FindChild<T>(DependencyObject parent, string childName)
        where T : DependencyObject
        {
            // Confirm parent and childName are valid.
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);

                    // If the child is found, break so we do not overwrite the found child.
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null &amp;&amp; frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
                    else
                    {
                        // recursively drill down the tree
                        foundChild = FindChild<T>(child, childName);

                        // If the child is found, break so we do not overwrite the found child.
                        if (foundChild != null) break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you Rachel. I will try this out and let you know how it works. -- I just wasn't sure if it was because of the Visual Tree or not. For my situation, is the above solution the best way?
@iimpact Just re-read your question, and no it won't work to dynamically add new columns to your DataGrid (unless you only ever add a single column). The reason is that you are re-using a single instance of your DataGridTextColumn. If you try to add a 2nd copy of that single instance, you will have two columns that contain the exact same header and data because you are referencing the exact same instance of the column. To dynamically add columns to a DataGrid you need to create a new DataGridTextColumn every time you need a new column.
Okay, thanks a lot. I understand how to create text columns programmatically, but how would the custom header be done?
@iimpact You can set the column's HeaderTemplate property to a DataTemplate that exists in your XAML. I believe you can also set the Header property itself, but keep in mind that if the header contains anything other than a string then you must re-create new instances of the Header UIElements every time you add a new column since you aren't using a Template

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.