I have a simple data structure class:
public class Client {
public String name {set; get;}
public String claim_number {set; get;}
}
Which I am feeding into a DataGrid
:
this.data_grid_clients.ItemSource = this.clients;
I would like to change the column headings. Ie: claim_number to "Claim Number". I know this can be done when you manually create the columns by doing something like:
this.data_grid_clients.Columns[0].Header = "Claim Number"
However, the Columns
property is empty when auto-generating the columns. Is there a way to rename the columns, or do I have to manually generate the columns?
You can use DisplayNameAttribute and update some part of your code to achieve what you want.
The first thing you have to do is, adding a [DisplayName("")]
to properties in the Client class.
public class Client {
[DisplayName("Column Name 1")]
public String name {set; get;}
[DisplayName("Clain Number")]
public String claim_number {set; get;}
}
The update you xaml code, add an event handler to AutoGenerationColumn event.
<dg:DataGrid AutoGenerateColumns="True" AutoGeneratingColumn="OnAutoGeneratingColumn">
</dg:DataGrid>
Finally, add a method to the code-behind.
private void OnAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
var displayName = GetPropertyDisplayName(e.PropertyDescriptor);
if (!string.IsNullOrEmpty(displayName))
{
e.Column.Header = displayName;
}
}
public static string GetPropertyDisplayName(object descriptor)
{
var pd = descriptor as PropertyDescriptor;
if (pd != null)
{
// Check for DisplayName attribute and set the column header accordingly
var displayName = pd.Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute;
if (displayName != null && displayName != DisplayNameAttribute.Default)
{
return displayName.DisplayName;
}
}
else
{
var pi = descriptor as PropertyInfo;
if (pi != null)
{
// Check for DisplayName attribute and set the column header accordingly
Object[] attributes = pi.GetCustomAttributes(typeof(DisplayNameAttribute), true);
for (int i = 0; i < attributes.Length; ++i)
{
var displayName = attributes[i] as DisplayNameAttribute;
if (displayName != null && displayName != DisplayNameAttribute.Default)
{
return displayName.DisplayName;
}
}
}
}
return null;
}
The nice answer
You can modify the Header
of the auto generated DataGridColumn
header in the AutoGeneratingColumn
event, where you can access the DisplayNameAttribute
Client.cs
public class Client
{
[DisplayName("Name")]
public String name { set; get; }
[DisplayName("Claim Number")]
public String claim_number { set; get; }
}
.xaml
<DataGrid ItemSource="{Binding Clients}"
AutoGenerateColumns="True"
AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" />
.xaml.cs
v1
// This snippet can be used if you can be sure that every
// member will be decorated with a [DisplayNameAttribute]
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
=> e.Column.Header = ((PropertyDescriptor)e.PropertyDescriptor).DisplayName;
v2
// This snippet is much safer in terms of preventing unwanted
// Exceptions because of missing [DisplayNameAttribute].
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyDescriptor is PropertyDescriptor descriptor)
{
e.Column.Header = descriptor.DisplayName ?? descriptor.Name;
}
}
You can use the AutoGeneratingColumns event.
private void dataGridAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName.StartsWith("MyColumn")
e.Column.Header = "Anything I Want";
}
MVVM answer
In order to keep this consistent with the MVVM pattern and avoid using the horrible code-behind, you can use custom behaviors from Sytem.Windows.Interactivity (part of the Expression Blend SDK found on nuget). You also need Windows.Base.dll in the project where you create the behaviors.
XAML
<DataGrid AutoGenerateColumns="True">
<i:Interaction.Behaviors>
<behaviours:ColumnHeaderBehaviour/>
</i:Interaction.Behaviors>
</DataGrid>
Behaviour Class
public class ColumnHeaderBehaviour : Behavior<DataGrid>
{
protected override void OnAttached()
{
AssociatedObject.AutoGeneratingColumn += OnGeneratingColumn;
}
protected override void OnDetaching()
{
AssociatedObject.AutoGeneratingColumn -= OnGeneratingColumn;
}
private static void OnGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs eventArgs)
{
if (eventArgs.PropertyDescriptor is PropertyDescriptor descriptor)
{
eventArgs.Column.Header = descriptor.DisplayName ?? descriptor.Name;
}
else
{
eventArgs.Cancel = true;
}
}
}
Behaviors are really useful and don't have to be defined in the same project as your views meaning that you can create a library of behaviors and use them in many applications.
I refactored the answer of Ekk to a shorter and Resharper compatible solution:
public static string GetPropertyDisplayName(object descriptor)
{
var propertyDescriptor = descriptor as PropertyDescriptor;
if (propertyDescriptor != null)
{
var displayName = propertyDescriptor.Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute;
if (displayName != null && !Equals(displayName, DisplayNameAttribute.Default))
{
return displayName.DisplayName;
}
}
else
{
var propertyInfo = descriptor as PropertyInfo;
if (propertyInfo != null)
{
var attributes = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), true);
foreach (object attribute in attributes)
{
var displayName = attribute as DisplayNameAttribute;
if (displayName != null && !Equals(displayName, DisplayNameAttribute.Default))
{
return displayName.DisplayName;
}
}
}
}
return null;
}
The short answer
You can modify the Header
of the auto generated DataGridColumn
header in the AutoGeneratingColumn
event.
.xaml
<DataGrid ItemSource="{Binding Clients}"
AutoGenerateColumns="True"
AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" />
.xaml.cs
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
switch (e.Name)
{
case nameof(Client.name):
e.Column.Header = "Name";
break;
case nameof(Client.claim_number):
e.Column.Header = "Claim Number";
break;
}
}
来源:https://stackoverflow.com/questions/13579034/how-do-you-rename-datagrid-columns-when-autogeneratecolumns-true