我有一个简单的数据结构类:
public class Client {
public String name {set; get;}
public String claim_number {set; get;}
}
我正在加入DataGrid
:
this.data_grid_clients.ItemSource = this.clients;
我想更改列标题。即:声明号码为“索赔号”。我知道这可以通过执行以下操作手动创建列来完成:
this.data_grid_clients.Columns[0].Header = "Claim Number"
但是,自动生成列时Columns
属性为空。有没有办法重命名列,还是我必须手动生成列?
答案 0 :(得分:32)
您可以使用DisplayNameAttribute并更新代码的某些部分,以达到您想要的效果。
您要做的第一件事是,在Client类的属性中添加[DisplayName("")]
。
public class Client {
[DisplayName("Column Name 1")]
public String name {set; get;}
[DisplayName("Clain Number")]
public String claim_number {set; get;}
}
更新xaml代码,为AutoGenerationColumn事件添加事件处理程序。
<dg:DataGrid AutoGenerateColumns="True" AutoGeneratingColumn="OnAutoGeneratingColumn">
</dg:DataGrid>
最后,在代码隐藏中添加一个方法。
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;
}
答案 1 :(得分:5)
您可以在Header
事件中修改自动生成的DataGridColumn
标题的AutoGeneratingColumn
,您可以在其中访问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;
}
}
答案 2 :(得分:2)
您可以使用AutoGeneratingColumns事件。
private void dataGridAutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (e.PropertyName.StartsWith("MyColumn")
e.Column.Header = "Anything I Want";
}
答案 3 :(得分:2)
为了使其与MVVM模式保持一致并避免使用背后的可怕代码,您可以使用Sytem.Windows.Interactivity(位于nuget上的Expression Blend SDK的一部分)中的自定义行为。在创建行为的项目中,您还需要Windows.Base.dll。
XAML
<DataGrid AutoGenerateColumns="True">
<i:Interaction.Behaviors>
<behaviours:ColumnHeaderBehaviour/>
</i:Interaction.Behaviors>
</DataGrid>
行为类别
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;
}
}
}
行为确实很有用,不必在与视图相同的项目中进行定义,这意味着您可以创建行为库并在许多应用程序中使用它们。
答案 4 :(得分:0)
我将Ekk的答案重构为更短且与Resharper兼容的解决方案:
CREATE PROCEDURE mark
@variable VARCHAR(max)
AS
BEGIN
DECLARE @sql NVARCHAR(Max)
SET @sql='update tab_A set Analyzed=1 where id IN ('''+Convert(NVARCHAR(max),@variable)+''') '
EXEC (@sql)
END
答案 5 :(得分:0)
您可以修改Header
事件中自动生成的DataGridColumn
标头的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;
}
}
答案 6 :(得分:0)
在附加到OnAutoGeneratingColumn方法的上下文中添加其他人所说的内容;我发现以下方法很有用。
它将确保它与其他视图模型一样使用视图模型属性中的DisplayName属性,但是如果未设置该名称,它将使用正则表达式采用Pascal大小写的名称并将其转换为漂亮的列标题。 / p>
//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();
}