问题
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?
回答1:
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;
}
回答2:
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;
}
}
回答3:
You can use the AutoGeneratingColumns event.
private void dataGridAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName.StartsWith("MyColumn")
e.Column.Header = "Anything I Want";
}
回答4:
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.
回答5:
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;
}
回答6:
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