浅析wpf中datagrid显示列的问题
作者:金士顿
这个会生成3列
List<Person> list = new List<Person>(); list.Add(new Person { Name = "张三", Age = 22, Address = "广东省廉江市车板镇大坝村" }); list.Add(new Person { Name = "李四", Age = 23, Address = "江西省景德镇市市辖区" }); list.Add(new Person { Name = "王五", Age = 24, Address = "上海市虹口区" });
这个也会有三列,怎么解决?
datagrid.ItemsSource = list; <DataGrid.Columns> <DataGridTextColumn Header="姓名" Binding="{Binding Name}" /> <DataGridTextColumn Header="年龄" Binding="{Binding Age}" /> <DataGridTextColumn Header="地址" Binding="{Binding Address}" /> </DataGrid.Columns>
从你提供的代码来看,DataGrid的列似乎被定义了两次:一次是通过绑定ItemsSource属性到一个包含Person对象的列表,另一次是在XAML中静态定义了三个DataGridTextColumn列。通常情况下,如果你没有设置AutoGenerateColumns="True",DataGrid应该不会自动生成列。不过,如果你发现实际运行的应用中列被重复添加了,这通常是因为AutoGenerateColumns属性默认为True,导致DataGrid既生成了基于数据源的列,也生成了XAML中定义的列。
要解决这个问题,确保AutoGenerateColumns属性被明确设置为False,以便DataGrid只使用XAML中定义的列:
<DataGrid x:Name="datagrid" SelectionMode="Extended" IsReadOnly="True" HorizontalAlignment="Left" AutoGenerateColumns="False" SelectionChanged="datagrid_Selected"> <DataGrid.Columns> <DataGridTextColumn Header="姓名" Binding="{Binding Name}" /> <DataGridTextColumn Header="年龄" Binding="{Binding Age}" /> <DataGridTextColumn Header="地址" Binding="{Binding Address}" /> </DataGrid.Columns> </DataGrid>
在这个修正中,添加了AutoGenerateColumns="False"到DataGrid的属性中,这将阻止DataGrid根据数据源自动创建列。这样,DataGrid将只显示在<DataGrid.Columns>节点中定义的列。
如果不适用这个AutoGenerateColumns=“False”,这段代码怎么修改比较好?
如果您不想使用 AutoGenerateColumns="False",那么您应该完全依赖于 DataGrid 自动从数据源生成列的功能,而不在 XAML 中显式声明列。
要做到这一点,您应该从 XAML 中移除 <DataGrid.Columns> 节点,因为 DataGrid 将根据绑定到 ItemsSource 的数据对象的公共属性自动为您生成列。这就要求您的数据对象(在此例中为 Person 类)的每个公共属性都将成为 DataGrid 的一个列。
以下是更新后的 XAML 示例,其中移除了列的静态定义:
<DataGrid x:Name="datagrid" SelectionMode="Extended" IsReadOnly="True" HorizontalAlignment="Left" SelectionChanged="datagrid_Selected"> <!-- DataGrid.Columns section is removed to rely on auto-generated columns --> </DataGrid>
在后台代码中,您保留对 ItemsSource 的设置:
public MainWindow() { InitializeComponent(); List<Person> list = new List<Person> { new Person { Name = "张三", Age = 22, Address = "广东省廉江市车板镇大坝村" }, new Person { Name = "李四", Age = 23, Address = "江西省景德镇市市辖区" }, new Person { Name = "王五", Age = 24, Address = "上海市虹口区" } }; datagrid.ItemsSource = list; }
这样做之后,当您运行应用程序,DataGrid 将仅显示来自 Person 对象列表的属性为列,而不会有任何在 XAML 中静态定义的列。这种方法的优点是简化了 XAML,使得任何对数据对象(如 Person 类)的更改都会自动反映在 DataGrid 的列上。缺点是您将失去在 XAML 中直接定义列时能够进行的细粒度控制,比如设置列宽和格式化。如果您需要这些控制,可以通过编程方式在后台代码中配置自动生成的列,或者简单地保留 AutoGenerateColumns="False" 并在 XAML 中显式定义您的列。
列显示的是英文,如果我想显示中文,或者其他语言怎么办?
如果您希望DataGrid中的列标题显示为中文或其他语言,而不是数据源中属性的名称,您可以在绑定时为每个列设置Header属性。如果您不使用AutoGenerateColumns="False",则无法在XAML中预先设置列标题,因为列是自动生成的。不过,您可以通过在代码后台中处理DataGrid的AutoGeneratingColumn事件来改变列标题。
以下是如何在后台代码中处理AutoGeneratingColumn事件以设置列标题为中文的示例:
在XAML中,为DataGrid添加AutoGeneratingColumn事件处理器:
<DataGrid x:Name="datagrid" SelectionMode="Extended" IsReadOnly="True" HorizontalAlignment="Left" SelectionChanged="datagrid_Selected" AutoGeneratingColumn="datagrid_AutoGeneratingColumn"> </DataGrid>
在后台代码(C#)中,添加datagrid_AutoGeneratingColumn事件处理器的实现:
private void datagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { // 检查正在生成的列并设置中文标题 if (e.PropertyName == "Name") { e.Column.Header = "姓名"; } else if (e.PropertyName == "Age") { e.Column.Header = "年龄"; } else if (e.PropertyName == "Address") { e.Column.Header = "地址"; } // 对于其他语言,也可以在此设置相应的标题 // 例如,如果您需要日语,可以设置为 e.Column.Header = "名前"; 等等 }
这段代码会检查每一个自动生成的列,并将其Header属性设置为您提供的中文字符串。这样,即使列是根据数据源的属性自动生成的,您仍然可以控制它们的显示标题。
这种方法提供了在运行时根据列的属性名来自定义列标题的灵活性,这样即使您使用的是自动生成列的功能,也可以实现多语言支持。
还有其他方法吗?
如果您希望在 DataGrid 中显示中文列名,并且不使用 AutoGenerateColumns="False" 属性,您还可以通过绑定到一个具有中文属性名称的数据源来解决。这涉及到使用数据转换器或创建一个包含中文属性名的新数据类型。但是,这通常不是推荐的方法,因为它可能涉及到重构您的数据模型以适应UI显示的需求,这并不是数据模型的最佳实践。
除了直接在 AutoGeneratingColumn 事件中设置列头之外,还有一些其他策略可以考虑:
使用资源文件进行国际化
如果您的应用程序需要支持多种语言,则可以使用资源文件来实现国际化:
为每种语言创建一个资源文件(例如,Resources.zh-CHS.resx 用于简体中文,Resources.en-US.resx 用于英文)。
在资源文件中为每个列名定义一个资源键值对。
在 AutoGeneratingColumn 事件中使用资源文件中的字符串替换默认列名。
private void datagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { e.Column.Header = Properties.Resources.ResourceManager.GetString(e.PropertyName); }
使用 DisplayName 属性
如果您的数据模型允许,您可以在模型属性上使用 DisplayName 属性来指定列名。DataGrid 并不直接使用这个属性,但是您可以在 AutoGeneratingColumn 事件中使用它来获取列名。
[DisplayName("姓名")] public string Name { get; set; }
然后,在 AutoGeneratingColumn 事件中读取这个属性:
private void datagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { var displayNameAttribute = e.PropertyDescriptor.Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute; if (displayNameAttribute != null) { e.Column.Header = displayNameAttribute.DisplayName; } }
显式声明列的绑定和列头
这不是自动化的方法,但它允许你在 XAML 中完全控制列的创建,包括列头和绑定。
在这种情况下,您会将 AutoGenerateColumns 设置为 False 并且显式声明每列,就像在之前的例子中一样。如果数据源的属性名称改变,您也需要更新 XAML 代码。
总结
AutoGeneratingColumn 事件处理器是处理自动生成列并为其指定自定义列头的标准方法。使用资源文件进行国际化或在数据模型中使用 DisplayName 属性可以提供额外的灵活性和多语言支持。在多种情况下,选择最佳方法取决于您应用程序的具体需求和数据模型的复杂性。
到此这篇关于浅析wpf中datagrid显示列的问题的文章就介绍到这了,更多相关wpf datagrid显示列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!