cannot find Name of DataGridColumn programmatically
Asked Answered
H

2

6

I found the Columns collection in my datagrid, and was hoping to iterate through it to find a certain column Name. However, I can't figure out how to address the x:Name attribute of the column. This xaml illustrates my problem with a DataGridTextColumn and a DataGridTemplateColumn:

<t:DataGrid x:Name="dgEmployees" ItemsSource="{Binding Employees}" 
    AutoGenerateColumns="false" Height="300" >
    <t:DataGrid.Columns>
        <t:DataGridTextColumn x:Name="FirstName" Header="FirstName"
Binding="{Binding FirstName}" />
        <t:DataGridTemplateColumn x:Name="LastName" Header="LastName" >
            <t:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding LastName}" />
                </DataTemplate>
            </t:DataGridTemplateColumn.CellTemplate>
        </t:DataGridTemplateColumn>
    </t:DataGrid.Columns>
</t:DataGrid>

And here is my code:

    DataGrid dg = this.dgEmployees;
    foreach (var column in dg.Columns) 
    {
        System.Console.WriteLine("name: " + (string)column.GetValue(NameProperty));
    }

At runtime, no value is present; column.GetValue doesn't return anything. Using Snoop, I confirmed that there is no Name property on either DataGridTextColumn or DataGridTemplateColumn.

What am I missing?

Husein answered 3/1, 2011 at 22:1 Comment(0)
B
14

WPF has two different, yet similar concepts, x:Name, which is used to create a field which references an element defined in XAML, i.e. connecting your code-behind to your XAML, and FrameworkElement.Name, which uniquely names an element within a namescope.

If an element has a FrameworkElement.Name property, x:Name will set this property to the value given in XAML. However, there are instances where it is useful to link non FrameworkElement elements to fields in code-behind, such as in your example.

See this related question:

In WPF, what are the differences between the x:Name and Name attributes?

As an alternative, you could define your own attached property which can be used to name the columns. The attached property is defined as follows:

public class DataGridUtil
{

    public static string GetName(DependencyObject obj)
    {
        return (string)obj.GetValue(NameProperty);
    }

    public static void SetName(DependencyObject obj, string value)
    {
        obj.SetValue(NameProperty, value);
    }

    public static readonly DependencyProperty NameProperty =
        DependencyProperty.RegisterAttached("Name", typeof(string), typeof(DataGridUtil), new UIPropertyMetadata(""));

}

You can then assign a name to each column ...

xmlns:util="clr-namespace:WPFDataGridExamples"

<t:DataGrid x:Name="dgEmployees" ItemsSource="{Binding Employees}" 
    AutoGenerateColumns="false" Height="300" >
    <t:DataGrid.Columns>
        <t:DataGridTextColumn util:DataGridUtil.Name="FirstName" Header="FirstName"
Binding="{Binding FirstName}" />
        <t:DataGridTemplateColumn util:DataGridUtil.Name="LastName" Header="LastName" >
            <t:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding LastName}" />
                </DataTemplate>
            </t:DataGridTemplateColumn.CellTemplate>
        </t:DataGridTemplateColumn>
    </t:DataGrid.Columns>
</t:DataGrid>

Then access this name in code as follows:

DataGrid dg = this.dgEmployees;
foreach (var column in dg.Columns) 
{
    System.Console.WriteLine("name: " + DataGridUtil.GetName(column));
}

Hope that helps

Bezanson answered 4/1, 2011 at 8:37 Comment(5)
Your message and link are informative. But I'm not sure how they answer my question. Are you saying that this code will not work since DataGridColumn is not a FrameworkElement? Can you suggest an alternate approach?Husein
Daniel, how about an attached property? See my edited answer above.Bezanson
Colin, that worked for me. Thank you. I wonder why they didn't make a 'Name' DP for DataGridColumns.Husein
thnaks for your great answer,how can i use this property in codebehind?for example i want to set name property for this columns: columnCollection = new ObservableCollection<DataGridTextColumn>(); columnCollection.Add(new DataGridTextColumn { Header = "ColumnHeader", Binding = new Binding("ColumnName)" , ??Name=????}); Edenedens
Sigh. -(Infinity) to Tinyflacid, I mean Microsoft, for not including a "Name" DependencyProperty in the DataGridColumn Class. I know much of the complexity (vs. WinForms) is (supposedly) needed for more flexibility, but I doubt they can claim that excuse in this case. And even with a "Name" DP, the Code Behind still needs to dupe the Magic String from XAML (ala when MS thought Magic Strings were ok in RaisePropertyChanged Call. SMH). WinForms created separate DataGridViewTextBoxColumn Objects in the *.Designer.cs with Names that could be Intellisensed / compile-time checked.Argybargy
C
1

You can use linq query to find name of the datagrid column Headers

dgvReports.Columns.Select(a=>a.Header.ToString()).ToList()

where dgvReports is name of the datagrid.

Cyprian answered 11/8, 2016 at 6:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.