Jak zmienić nazwy kolumn DataGrid, jeśli AutoGenerateColumns = True?


Mam prostą klasę struktury danych:
public class Client {
public String name {set; get;}
public String claim_number {set; get;}
}

Które przekazuję do
DataGrid
:
this.data_grid_clients.ItemSource = this.clients;

Chciałbym zmienić nagłówki kolumn. To znaczy: numer_ roszczenia w polu „Numer roszczenia”. Wiem, że można to zrobić, tworząc ręcznie kolumny, wykonując coś takiego:
this.data_grid_clients.Columns[0].Header = "Claim Number"

Jednak właściwość
Columns
jest pusta podczas automatycznego generowania kolumn. Czy istnieje sposób zmiany nazw kolumn, czy też muszę ręcznie wygenerować kolumny?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

możesz użyć

DisplayNameAttribute
http://msdn.microsoft.com/en-u ... .aspx
i zaktualizuj część swojego kodu, aby osiągnąć to, czego chcesz.
Pierwszą rzeczą, którą musisz zrobić, jest dodanie
[DisplayName („”)]
do właściwości w klasie klienta.
public class Client {
[DisplayName("Column Name 1")]
public String name {set; get;} [DisplayName("Clain Number")]
public String claim_number {set; get;}
}

Zaktualizuj kod XAML, dodaj procedurę obsługi zdarzeń do zdarzenia AutoGenerationColumn.
<dg:DataGrid AutoGenerateColumns="True" AutoGeneratingColumn="OnAutoGeneratingColumn">
</dg:DataGrid>

Na koniec dodaj metodę do sekcji kodu.
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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Dobra odpowiedź
>
Możesz się zmienić
Header
https://msdn.microsoft.com/en- ... .aspx
automatycznie wygenerowany nagłówek
DataGridColumn
w zdarzeniu
AutoGeneratingColumn
, do którego można uzyskać dostęp
DisplayNameAttribute
https://msdn.microsoft.com/en- ... .aspx

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;
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz użyć zdarzenia AutoGeneratingColumns.
private void dataGridAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName.StartsWith("MyColumn")
e.Column.Header = "Anything I Want";
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Odpowiedź MVVM
>
Aby zachować zgodność ze wzorcem MVVM i uniknąć używania okropnego kodu, możesz użyć niestandardowych zachowań z Sytem.Windows.Interactivity (część wyrażenia Blend SDK znajdującego się w nuget). Będziesz także potrzebował pliku Windows.Base.dll w projekcie, w którym tworzysz zachowanie.

XAML

<DataGrid AutoGenerateColumns="True">
<i:Interaction.Behaviors>
<behaviours:ColumnHeaderBehaviour/>
</i:Interaction.Behaviors>
</DataGrid>


Klasa zachowania

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;
}
}
}

Zachowania są naprawdę przydatne i nie muszą być definiowane w tym samym projekcie co Twoje widoki, co oznacza, że ​​możesz stworzyć bibliotekę zachowań i używać ich w wielu aplikacjach.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Krótka odpowiedź
>
Możesz się zmienić
Header
https://msdn.microsoft.com/en- ... .aspx
automatycznie wygenerowany nagłówek
DataGridColumn
w zdarzeniu
AutoGeneratingColumn
.

.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;
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Sparafrazowałem odpowiedź Ekka na krótsze i bardziej kompatybilne rozwiązanie Resharper:
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;
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Inna metoda generowania nagłówków kolumn
>
Aby dodać do tego, co stwierdzili inni w kontekście dołączania do metody OnAutoGeneratingColumn, uważam, że pomocne jest następujące podejście.
Zapewni, że użyje atrybutu DisplayName z właściwości viewmodel, tak jak inne, ale jeśli nie zostanie podana nazwa, użyje wyrażenia regularnego, aby wziąć nazwę z literami Pascal i przekształcić ją w ładny nagłówek kolumny.
//Note that I cleaned this up after I pasted it into the Stackoverflow Window, I don't
//think I caused any compilation errors but you have been warned.
private void InvoiceDetails_OnAutoGeneratingColumn(object sender,
DataGridAutoGeneratingColumnEventArgs e)
{
if (!(e.PropertyDescriptor is PropertyDescriptor descriptor)) return;//You cannot just use descriptor.DisplayName because it provides you a value regardless to it
// being manually set. This approach only uses a DisplayName that was manually set on a view
// model property.
if (descriptor.Attributes[typeof(DisplayNameAttribute)]
is DisplayNameAttribute displayNameAttr
&& !string.IsNullOrEmpty(displayNameAttr.DisplayName))
{
e.Column.Header = displayNameAttr.DisplayName;
return;
}//If you only wanted to display columns that had DisplayName set you could collapse the ones
// that didn't with this line.
//e.Column.Visibility = Visibility.Collapsed;
//return;//This alternative approach uses regular expressions and does not require
//DisplayName be manually set. It will Breakup Pascal named variables
//"NamedLikeThis" into nice column headers that are "Named Like This".
e.Column.Header = Regex.Replace(descriptor.Name,
@"((?<=[A-Z])([A-Z])(?=[a-z]))|((?<=[a-z]+)([A-Z]))",
@" $0",
RegexOptions.Compiled)
.Trim(); }

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się