Thứ ba, ngày 21 tháng 11 năm 2017

WPF – Multi Language với Binding và ResourceDictionary

Ngày đăng: 28/3/2012, 9:5:27PM | Lượt xem: 9,690
Hot!

Sử dụng tính năng binding trong WPF, bạn có thể tạo được các ứng dụng đa ngôn ngữ rất đơn giản với sự trợ giúp của ResourceDictionary. Lợi ích của phương pháp này là bạn không cần phải viết code để thay đổi văn bản hiển thị của các control và việc thiết kế giao diện cũng không có gì khác biệt.

Sử dụng tính năng binding trong WPF, bạn có thể tạo được các ứng dụng đa ngôn ngữ rất đơn giản với sự trợ giúp của ResourceDictionary. Lợi ích của phương pháp này là bạn không cần phải viết code để thay đổi văn bản hiển thị của các control và việc thiết kế giao diện cũng không có gì khác biệt.


Download demo+sourcecode (22KB)

Các ResourceDictionary

Với mỗi ngôn ngữ, bạn cần tạo một ResourceDictionary tương ứng với tên bất kì. Để thêm các phần tử kiểu String, bạn cần khai báo thêm namespace clr-namespace:System;assembly=mscorlib.

Để bắt đầu tôi tạo một dự án WPF với tên WPFMultiLanguage, sau đó thêm thư mục “Lang” trong solution explorer và thêm hai ResourceDictionary với tên Vietnamese.xaml và English.xaml vào đó. Nội dung của hai tập tin này như sau:

Vietnamese.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <sys:String x:Key="File">Hồ sơ</sys:String>
    <sys:String x:Key="ClickHere">Nhấn vào đây</sys:String>
    <sys:String x:Key="Open">Mở</sys:String>
    <sys:String x:Key="Language">Ngôn ngữ</sys:String>
    <sys:String x:Key="English">English</sys:String>
    <sys:String x:Key="Vietnamese">Tiếng Việt</sys:String>
    <sys:String x:Key="Hello">Xin chào</sys:String>
</ResourceDictionary>

English.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <sys:String x:Key="File">File</sys:String>
    <sys:String x:Key="ClickHere">Click Here</sys:String>
    <sys:String x:Key="Language">Language</sys:String>
    <sys:String x:Key="English">English</sys:String>
    <sys:String x:Key="Vietnamese">Tiếng Việt</sys:String>
    <sys:String x:Key="Hello">Hello</sys:String>
</ResourceDictionary>

Cửa sổ chính: MainWindow

Trong cửa sổ chính MainWindow, tôi tạo các MenuItem cho mỗi ngôn ngữ mà chương trình hỗ trợ. Tôi dùng thuộc tính MenuItem.Tag để lưu tên culture, nhờ đó việc thay đổi ngôn ngữ sẽ dễ dàng hơn bằng cách lấy trực tiếp từ đối tượng MenuItem được click.

Do việc lựa chọn ResourceDictionary sẽ diễn ra trong code-behind nên ta trong quá trình thiết kế, bộ phân tích XAML sẽ không nhận ra các resource bạn dùng trong binding. Hãy bỏ qua các cảnh báo lỗi đó và thiết kế như bình thường.

MainWindow.xaml:

<Window x:Class="WPFMultiLanguage.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WPF MultiLanguage" Height="250" Width="300">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="{DynamicResource File}" />
            <MenuItem Header="{DynamicResource Language}" Name="languageMenuItem" >
                <MenuItem Header="{DynamicResource English}" Tag="en-US" Click="MenuItem_Click" IsChecked="True"/>
                <MenuItem Header="{DynamicResource Vietnamese}" Tag="vi-VN" Click="MenuItem_Click"/>
            </MenuItem>
        </Menu>
        <Button Content="{DynamicResource ClickHere}"
                HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" />
    </DockPanel>
</Window>

Trong code-behind, tôi tạo phương thức ApplyLanguage() với một tham số cultureName tùy chọn để thay đổi giá trị của Thread.CurrentThread.CurrentCulture. Đây là giá trị được sử dụng để xác định ngôn ngữ mà chương trình sử dụng:

private void ApplyLanguage(string cultureName = null)
{
    if (cultureName != null)
        Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);

    ResourceDictionary dict = new ResourceDictionary();
    switch (Thread.CurrentThread.CurrentCulture.ToString())
    {
        case "vi-VN":
            dict.Source = new Uri("..\\Lang\\Vietnamese.xaml", UriKind.Relative);
            break;
        // ...
        default:
            dict.Source = new Uri("..\\Lang\\English.xaml", UriKind.Relative);
            break;
    }
    this.Resources.MergedDictionaries.Add(dict);

    // check/uncheck the language menu items based on the current culture
    foreach (var item in languageMenuItem.Items)
    {
        MenuItem menuItem = item as MenuItem;
        if (menuItem.Tag.ToString() == Thread.CurrentThread.CurrentCulture.Name)
            menuItem.IsChecked = true;
        else
            menuItem.IsChecked = false;
    }
}

Phương thức xử lý sự kiện của các MenuItem và Button:

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
    MenuItem menuItem = sender as MenuItem;

    ApplyLanguage(menuItem.Tag.ToString());
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    SettingDialog dialog = new SettingDialog();
    dialog.Owner = this;
    if (dialog.ShowDialog() == true)
    {
        ApplyLanguage();
    }
}

Hộp thoại lựa chọn ngôn ngữ: SettingDialog

Hộp thoại này được bổ sung nhằm hướng dẫn cách thay đổi ngôn ngữ của cửa sổ chính thông qua một hộp thoại. Bằng cách gọi phương thức ShowDialog() và kiểm tra giá trị trả về bằng true, ta sẽ tiến hành thay đổi giao diện của cửa sổ chính.

Ở đây không cần thiết phải tạo biến để truyền giữa hai cửa sổ vì ta sẽ sử dụng giá trị Thread.CurrentThread.CurrentCulture như đã nói ở trên.

SettingDialog.xaml:

<Window x:Class="WPFMultiLanguage.SettingDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        ShowInTaskbar="False"
        WindowStartupLocation="CenterOwner"
        WindowStyle="ToolWindow"
        Title="Choose Language" Height="150" Width="300">
    <Window.Resources>
        <Style x:Key="controlStyle" TargetType="Control">
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </Style>
        <Style TargetType="Button" BasedOn="{StaticResource controlStyle}">
            <Setter Property="Height" Value="30"/>
            <Setter Property="Width" Value="80"/>
        </Style>
        <Style TargetType="RadioButton" BasedOn="{StaticResource controlStyle}">
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.ColumnSpan="2" Margin="10,5,0,0">Please choose the desired language:</TextBlock>
        <RadioButton Content="English" Name="radEnglish" Grid.Row="1"/>
        <RadioButton Content="Tiếng Việt" Name="radVietnamese" Grid.Row="1" Grid.Column="1"/>
        <Button Content="OK" Grid.Row="2" Click="OkButton_Click" />
        <Button Content="Cancel" Grid.Row="2" Grid.Column="1" Click="CancelButton_Click" />
    </Grid>

</Window>

Và code-behind SettingDialog.xaml.cs:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Threading;

namespace WPFMultiLanguage
{
    ///
<summary> /// Interaction logic for SettingDialog.xaml
 /// </summary>
    public partial class SettingDialog : Window
    {
        public SettingDialog()
        {
            InitializeComponent();

            if (Thread.CurrentThread.CurrentCulture.Name == "en-US")
                radEnglish.IsChecked = true;
            else
                radVietnamese.IsChecked = true;

        }

        private void OkButton_Click(object sender, RoutedEventArgs e)
        {
            if(radEnglish.IsChecked==true)
                Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
            else
                Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("vi-VN");
            DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

Giao diện:

http://yinyangit.wordpress.com

Bài liên quan:

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
ca do bong da online
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.