No puede encontrar el nombre de DataGridColumn mediante programación
-
14-10-2019 - |
Pregunta
He encontrado la colección Columns en mi cuadrícula de datos, y esperaba para iterar a través de él para encontrar una determinada columna Nombre. Sin embargo, no puedo encontrar la manera de abordar la x: Nombre de atributo de la columna. Este xaml ilustra mi problema con un DataGridTextColumn y una 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>
Y aquí es mi código:
DataGrid dg = this.dgEmployees;
foreach (var column in dg.Columns)
{
System.Console.WriteLine("name: " + (string)column.GetValue(NameProperty));
}
En tiempo de ejecución, ningún valor está presente; column.GetValue no devuelve nada. El uso de Snoop, me confirmó que no hay propiedad Name a ambos DataGridTextColumn o DataGridTemplateColumn.
¿Qué me falta?
Solución
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
Otros consejos
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.