WPF DataGrid 在 AutoGenerateColumns 的狀態產生多國語的欄位標題。
使用 WPF DataGrid 元素時,為了方便有時會採用自動產生欄位的方式,以 DataGrid ItemsSource 來自於 ObservableCollection<T>、List<T> 等等集合物件的狀況,若沒有其他任何設定,欄位的標題(Header)會直接採用該對應屬性的名稱。這個情形下,我們要如何讓標題能夠以多國語的方式呈現呢?我們一步一步的來完成這個需求。
為了方便起見,我們不談太多甚麼 Notify Property Changed 這類的事情,直接使用一個 List<T> 來當作 DataGrid ItemsSource 來源。
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class MainViewModel
{
public List<Person> People { get; set; }
public MainViewModel()
{
People = new List<Person>
{
new Person {Name = "Bill" , Age = 25},
new Person {Name = "David" , Age = 27}
};
}
}
<Window x:Class="DataGridHeaderLanguage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridHeaderLanguage"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext >
<local:MainViewModel />
</Window.DataContext>
<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding People}" >
</DataGrid>
</Window>
接下來的步驟要為語言建立資源檔案 (resx),一個是預設語系,一個是繁中語系。
註:因為這個資源檔可能會在 xaml 的其他位置使用 x:Static 來取得,所以要把存取修飾詞改為 public。
DataGrid 具有一個事件稱為 AutoGeneratingColumn Event ,每當 DataGrid 自動產生一個 Coulmn 的時候,就會引發這個事件,這也正是這一篇的重點。
(1) 最簡單直覺的作法:直接為該事件撰寫事件委派函式並且掛上,簡單有效,但就是看起來沒這麼炫。
<Window x:Class="DataGridHeaderLanguage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridHeaderLanguage"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext >
<local:MainViewModel />
</Window.DataContext>
<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding People}" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn">
</DataGrid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column.Header = AppResource.ResourceManager.GetString(e.Column.Header.ToString());
}
}
這樣就完成了,簡單吧。但這樣的寫法遇到極偏好 MVVM 方式的開發者可能就不喜歡了。
(2) 所以來改裝一下,應用 Behavior<T>,這個類別來自於 Blend SDK 裡的System.Windows.Interactivity 組件,得先將此組件加入參考。接著撰寫自訂的 Behavior
public class ColumnBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
AssociatedObject.AutoGeneratingColumn += AssociatedObject_AutoGeneratingColumn;
}
private void AssociatedObject_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
e.Column.Header = AppResource.ResourceManager.GetString(e.Column.Header.ToString());
}
protected override void OnDetaching()
{
AssociatedObject.AutoGeneratingColumn -= AssociatedObject_AutoGeneratingColumn;
}
}
修改 xaml code (此時可以移除之前寫的事件委派函式),掛上 Behavior
<Window x:Class="DataGridHeaderLanguage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataGridHeaderLanguage"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext >
<local:MainViewModel />
</Window.DataContext>
<DataGrid AutoGenerateColumns="True" ItemsSource="{Binding People}" >
<i:Interaction.Behaviors >
<local:ColumnBehavior />
</i:Interaction.Behaviors>
</DataGrid>
</Window>
大功告成,以後任何的 DataGrid 都可以套用這個 ColumnBehavior 自動載入多國語系的 Header 了。
source : https://github.com/billchungiii/DataGridHeaderLanguage