如何仅将 SelectionChanged 事件绑定到 XAML 中其他元素的可见性 属性
How to bind SelectionChanged Event to Visibility Property on other Element in XAML Only
给定的是 SelectionChanged 后的 ComboBox 应该变成可见的 TextBlock。我使用 ViemModel 构建此功能。
查看:
<ComboBox SelectionChanged="{mvvmHelper:EventBinding OnSelectionChanged}" />
<TextBlock Visibility="{Binding LanguageChanged, Converter={StaticResource BooleanVisibilityConverter}}"/>
视图模型:
bool LanguageChanged = false;
void OnSelectionChanged() => LanguageChanged = true;
我正在寻找仅在 XAML 中完成的优雅解决方案
到目前为止我尝试了什么:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsDropDownOpen, ElementName=Box, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
我想我必须使用 Storyboard
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<EventTrigger RoutedEvent="SelectionChanged">
<BeginStoryboard>
<Storyboard>
???
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
另一个选项是 System.Windows.Interactivity 但这在 WpfCore 3.1 中不可用
这里有几个不错的选择。
由于使用 DataTrigger
的最后一个解决方案是最灵活的,因为它允许触发 ComboBox.SelectedItem
的某些状态,我建议实施它来解决您的问题。它也是一个仅 XAML 的解决方案,不需要像 LanguageChanged
.
这样的额外 属性
为触发器设置动画 属性
为了使 属性 像 LanguageChanged
一样动画,属性 必须是 DependencyProperty
。因此,第一个示例将 LanguageChanged
实现为 MainWindow
:
的 DependencyProperty
MainWindow.xaml.cs
partial class MainWindow : Window
{
public static readonly DependencyProperty LanguageChangedProperty = DependencyProperty.Register(
"LanguageChanged",
typeof(bool),
typeof(MainWindow),
new PropertyMetadata(default(bool)));
public bool LanguageChanged
{
get => (bool) GetValue(MainWindow.LanguageChangedProperty);
set => SetValue(MainWindow.LanguageChangedProperty, value);
}
}
MainWindow.xaml
<Window x:Name="Window">
<StackPanel>
<TextBlock Text="Invisible"
Visibility="{Binding RelativeSource={RelativeSource AncestorType=MainWindow}, Path=LanguageChanged, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ComboBox>
<ComboBox.Triggers>
<EventTrigger RoutedEvent="ComboBox.SelectionChanged">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="Window"
Storyboard.TargetProperty="LanguageChanged">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ComboBox.Triggers>
</ComboBox>
</StackPanel>
</Window>
直接对目标控件进行动画处理
如果您希望切换其可见性的控件与触发控件在同一范围内,您可以直接为 Visibility
设置动画:
MainWindow.xaml
<Window x:Name="Window">
<StackPanel>
<TextBlock x:Name="InvisibleTextBlock"
Text="Invisible"
Visibility="Hidden" />
<ComboBox>
<ComboBox.Triggers>
<EventTrigger RoutedEvent="ComboBox.SelectionChanged">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvisibleTextBlock"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ComboBox.Triggers>
</ComboBox>
</StackPanel>
</Window>
实现 IValueConverter
如果您希望向触发器添加更多条件,例如选择了哪个值,您应该将 TextBlock.Visibility
绑定到 ComboBox.SelectedItem
并使用 IValueConverter
来决定是否 return Visibility.Visible
或 Visibilty.Hidden
基于当前选择的项目:
MainWindow.xaml
<Window x:Name="Window">
<Window.Resources>
<!-- TODO::Implement IValueConverter -->
<SelectedItemToVisibilityConverter x:Key="SelectedItemToVisibilityConverter" />
</Window.Resources>
<StackPanel>
<TextBlock Text="Invisible"
Visibility="{Binding ElementName=LanguageSelector, Path=SelectedItem, Converter={StaticResource SelectedItemToVisibilityConverter}}" />
<ComboBox x:Name="LanguageSelector" />
</StackPanel>
</Window>
在 TextBlock 上实现 DataTrigger
如果您希望向触发器添加更多条件,例如选择了哪个值,您还可以将 DataTrigger
添加到 TetxtBlock
,它会触发 [= 的一个或多个属性16=]。然后,您必须将 SelectedItem
转换为基础 ComboBox
项目的实际类型,以便在绑定路径中引用项目的属性。
以下示例将 SelectedItem
转换为虚构类型 LanguageItem
以访问 LanguageItem.LanguageName
属性,以触发特定的选定语言:
MainWindow.xaml
<Window x:Name="Window">
<StackPanel>
<TextBlock x:Name="InvisibleTextBlock" Text="Invisible">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=LanguageSelector, Path=SelectedItem.(LanguageItem.LanguageName)}"
Value="English">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ComboBox x:Name="LanguageSelector" />
</StackPanel>
</Window>
我觉得@BionicCode 给出了相当全面的答案,但我会加上我的 2¢。
我认为最符合您要求的方案是样式触发器。
我看到 Bionic 包含了它,但这里有一个 MCVE:
<Window x:Class="project-name.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="120" Width="300">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="15,15,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Language: " VerticalAlignment="Center"/>
<ComboBox x:Name="LanguageCB" HorizontalAlignment="Left" SelectedIndex="0">
<ComboBoxItem Content="None ?"/>
<ComboBoxItem Content="English"/>
</ComboBox>
</StackPanel>
<Border Margin="0,10,0,0" BorderThickness="1" BorderBrush="Black" Padding="2">
<TextBlock Text="Becomes visible when "LanguageCB" changes selection">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=LanguageCB, Path=SelectedIndex}" Value="1">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
</StackPanel>
</Window>
但是...如果您真的在您的应用程序中进行本地化而不只是以此为例,那么我认为有更好的解决方案。
首先花几分钟阅读一下 WPF Globalization and Localization.
然后将至少 1 个语言资源文件添加到项目的属性中(例如 'Resources.ja-JP.resx',并且不要忘记将 Resources.resx 文件标记为 public。放一些本地化的这些 .resx 文件中的字符串。
然后将您的 TextBlock 的文本绑定到 属性:
<TextBlock Text="{Binding Path=ResourceName, Source={StaticResource Resources}}"/>
接下来您需要一些代码来处理切换区域性。
这里有很多选项,但我将包含一些我过去使用过的代码。
CultureResources.cs
namespace Multi_Language_Base_App.Cultures
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Diagnostics;
using System.Windows.Data;
/// <summary>
/// Wraps up XAML access to instance of Properties.Resources,
/// list of available cultures, and method to change culture </summary>
public class CultureResources
{
private static ObjectDataProvider provider;
public static event EventHandler<EventArgs> CultureUpdateEvent;
//only fetch installed cultures once
private static bool bFoundInstalledCultures = false;
private static List<CultureInfo> pSupportedCultures = new List<CultureInfo>();
/// <summary>
/// List of available cultures, enumerated at startup
/// </summary>
public static List<CultureInfo> SupportedCultures
{
get { return pSupportedCultures; }
}
public CultureResources()
{
if (!bFoundInstalledCultures)
{
//determine which cultures are available to this application
Debug.WriteLine("Get Installed cultures:");
CultureInfo tCulture = new CultureInfo("");
foreach (string dir in Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory))
{
try
{
//see if this directory corresponds to a valid culture name
DirectoryInfo dirinfo = new DirectoryInfo(dir);
tCulture = CultureInfo.GetCultureInfo(dirinfo.Name);
//determine if a resources dll exists in this directory that matches the executable name
string exe = System.Reflection.Assembly.GetExecutingAssembly().Location;
if (dirinfo.GetFiles(Path.GetFileNameWithoutExtension(exe) + ".resources.dll").Length > 0)
{
pSupportedCultures.Add(tCulture);
Debug.WriteLine(string.Format(" Found Culture: {0} [{1}]", tCulture.DisplayName, tCulture.Name));
}
}
catch (ArgumentException) //ignore exceptions generated for any unrelated directories in the bin folder
{
}
}
bFoundInstalledCultures = true;
}
}
/// <summary>
/// The Resources ObjectDataProvider uses this method to get
/// an instance of the _This Application Namespace_.Properties.Resources class
/// </summary>
public Properties.Resources GetResourceInstance()
{
return new Properties.Resources();
}
public static ObjectDataProvider ResourceProvider
{
get
{
if (provider == null)
provider = (ObjectDataProvider)App.Current.FindResource("Resources");
return provider;
}
}
/// <summary>
/// Change the current culture used in the application.
/// If the desired culture is available all localized elements are updated.
/// </summary>
/// <param name="culture">Culture to change to</param>
public static void ChangeCulture(CultureInfo culture)
{
// Remain on the current culture if the desired culture cannot be found
// - otherwise it would revert to the default resources set, which may or may not be desired.
if (pSupportedCultures.Contains(culture))
{
Properties.Resources.Culture = culture;
ResourceProvider.Refresh();
RaiseCultureUpdateEvent(null, new EventArgs());
Debug.WriteLine(string.Format("Culture changed to [{0}].", culture.NativeName));
}
else
{
Debug.WriteLine(string.Format("Culture [{0}] not available", culture));
}
}
private static void RaiseCultureUpdateEvent(object sender, EventArgs e)
{
EventHandler<EventArgs> handleit = CultureUpdateEvent;
CultureUpdateEvent?.Invoke(sender, e);
}
}
}
拼图的最后一块应该是提供对来自 xaml 的文化资源的访问的方法。这是使用 ObjectDataProvider 完成的。
您可以直接将其放入 App.xaml 或单独的文件中并在 App.xaml 中引用它。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Cultures="clr-namespace:Multi_Language_Base_App.Cultures">
<!-- Contains the current instance of the ProjectName.Properties.Resources class.
Used in bindings to get localized strings and automatic updates when the culture is updated -->
<ObjectDataProvider x:Key="Resources"
ObjectType="{x:Type Cultures:CultureResources}"
MethodName="GetResourceInstance"/>
<!-- Provides access to list of currently available cultures -->
<ObjectDataProvider x:Key="CultureResourcesDS"
ObjectType="{x:Type Cultures:CultureResources}"/>
</ResourceDictionary>
执行此操作时,您的字符串绑定可以从一开始就自动匹配系统区域性(或者最终成为通用资源中的默认值)。用户还可以即时切换文化。
在您的示例中,ComboBox SelectionChanged 事件将用作改变区域性的起点,如下所示:
CultureInfo CultureJapanese = new CultureInfo("ja-JP");
Cultures.CultureResources.ChangeCulture(CultureJapanese);
我更喜欢使用命令来完成这件事,但这取决于你。
给定的是 SelectionChanged 后的 ComboBox 应该变成可见的 TextBlock。我使用 ViemModel 构建此功能。
查看:
<ComboBox SelectionChanged="{mvvmHelper:EventBinding OnSelectionChanged}" />
<TextBlock Visibility="{Binding LanguageChanged, Converter={StaticResource BooleanVisibilityConverter}}"/>
视图模型:
bool LanguageChanged = false;
void OnSelectionChanged() => LanguageChanged = true;
我正在寻找仅在 XAML 中完成的优雅解决方案
到目前为止我尝试了什么:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsDropDownOpen, ElementName=Box, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
我想我必须使用 Storyboard
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<EventTrigger RoutedEvent="SelectionChanged">
<BeginStoryboard>
<Storyboard>
???
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
另一个选项是 System.Windows.Interactivity 但这在 WpfCore 3.1 中不可用
这里有几个不错的选择。
由于使用 DataTrigger
的最后一个解决方案是最灵活的,因为它允许触发 ComboBox.SelectedItem
的某些状态,我建议实施它来解决您的问题。它也是一个仅 XAML 的解决方案,不需要像 LanguageChanged
.
为触发器设置动画 属性
为了使 属性 像 LanguageChanged
一样动画,属性 必须是 DependencyProperty
。因此,第一个示例将 LanguageChanged
实现为 MainWindow
:
DependencyProperty
MainWindow.xaml.cs
partial class MainWindow : Window
{
public static readonly DependencyProperty LanguageChangedProperty = DependencyProperty.Register(
"LanguageChanged",
typeof(bool),
typeof(MainWindow),
new PropertyMetadata(default(bool)));
public bool LanguageChanged
{
get => (bool) GetValue(MainWindow.LanguageChangedProperty);
set => SetValue(MainWindow.LanguageChangedProperty, value);
}
}
MainWindow.xaml
<Window x:Name="Window">
<StackPanel>
<TextBlock Text="Invisible"
Visibility="{Binding RelativeSource={RelativeSource AncestorType=MainWindow}, Path=LanguageChanged, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ComboBox>
<ComboBox.Triggers>
<EventTrigger RoutedEvent="ComboBox.SelectionChanged">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="Window"
Storyboard.TargetProperty="LanguageChanged">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ComboBox.Triggers>
</ComboBox>
</StackPanel>
</Window>
直接对目标控件进行动画处理
如果您希望切换其可见性的控件与触发控件在同一范围内,您可以直接为 Visibility
设置动画:
MainWindow.xaml
<Window x:Name="Window">
<StackPanel>
<TextBlock x:Name="InvisibleTextBlock"
Text="Invisible"
Visibility="Hidden" />
<ComboBox>
<ComboBox.Triggers>
<EventTrigger RoutedEvent="ComboBox.SelectionChanged">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="InvisibleTextBlock"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ComboBox.Triggers>
</ComboBox>
</StackPanel>
</Window>
实现 IValueConverter
如果您希望向触发器添加更多条件,例如选择了哪个值,您应该将 TextBlock.Visibility
绑定到 ComboBox.SelectedItem
并使用 IValueConverter
来决定是否 return Visibility.Visible
或 Visibilty.Hidden
基于当前选择的项目:
MainWindow.xaml
<Window x:Name="Window">
<Window.Resources>
<!-- TODO::Implement IValueConverter -->
<SelectedItemToVisibilityConverter x:Key="SelectedItemToVisibilityConverter" />
</Window.Resources>
<StackPanel>
<TextBlock Text="Invisible"
Visibility="{Binding ElementName=LanguageSelector, Path=SelectedItem, Converter={StaticResource SelectedItemToVisibilityConverter}}" />
<ComboBox x:Name="LanguageSelector" />
</StackPanel>
</Window>
在 TextBlock 上实现 DataTrigger
如果您希望向触发器添加更多条件,例如选择了哪个值,您还可以将 DataTrigger
添加到 TetxtBlock
,它会触发 [= 的一个或多个属性16=]。然后,您必须将 SelectedItem
转换为基础 ComboBox
项目的实际类型,以便在绑定路径中引用项目的属性。
以下示例将 SelectedItem
转换为虚构类型 LanguageItem
以访问 LanguageItem.LanguageName
属性,以触发特定的选定语言:
MainWindow.xaml
<Window x:Name="Window">
<StackPanel>
<TextBlock x:Name="InvisibleTextBlock" Text="Invisible">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=LanguageSelector, Path=SelectedItem.(LanguageItem.LanguageName)}"
Value="English">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ComboBox x:Name="LanguageSelector" />
</StackPanel>
</Window>
我觉得@BionicCode 给出了相当全面的答案,但我会加上我的 2¢。
我认为最符合您要求的方案是样式触发器。
我看到 Bionic 包含了它,但这里有一个 MCVE:
<Window x:Class="project-name.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="120" Width="300">
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="15,15,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Language: " VerticalAlignment="Center"/>
<ComboBox x:Name="LanguageCB" HorizontalAlignment="Left" SelectedIndex="0">
<ComboBoxItem Content="None ?"/>
<ComboBoxItem Content="English"/>
</ComboBox>
</StackPanel>
<Border Margin="0,10,0,0" BorderThickness="1" BorderBrush="Black" Padding="2">
<TextBlock Text="Becomes visible when "LanguageCB" changes selection">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=LanguageCB, Path=SelectedIndex}" Value="1">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Border>
</StackPanel>
</Window>
但是...如果您真的在您的应用程序中进行本地化而不只是以此为例,那么我认为有更好的解决方案。
首先花几分钟阅读一下 WPF Globalization and Localization.
然后将至少 1 个语言资源文件添加到项目的属性中(例如 'Resources.ja-JP.resx',并且不要忘记将 Resources.resx 文件标记为 public。放一些本地化的这些 .resx 文件中的字符串。
然后将您的 TextBlock 的文本绑定到 属性:
<TextBlock Text="{Binding Path=ResourceName, Source={StaticResource Resources}}"/>
接下来您需要一些代码来处理切换区域性。 这里有很多选项,但我将包含一些我过去使用过的代码。
CultureResources.cs
namespace Multi_Language_Base_App.Cultures
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Diagnostics;
using System.Windows.Data;
/// <summary>
/// Wraps up XAML access to instance of Properties.Resources,
/// list of available cultures, and method to change culture </summary>
public class CultureResources
{
private static ObjectDataProvider provider;
public static event EventHandler<EventArgs> CultureUpdateEvent;
//only fetch installed cultures once
private static bool bFoundInstalledCultures = false;
private static List<CultureInfo> pSupportedCultures = new List<CultureInfo>();
/// <summary>
/// List of available cultures, enumerated at startup
/// </summary>
public static List<CultureInfo> SupportedCultures
{
get { return pSupportedCultures; }
}
public CultureResources()
{
if (!bFoundInstalledCultures)
{
//determine which cultures are available to this application
Debug.WriteLine("Get Installed cultures:");
CultureInfo tCulture = new CultureInfo("");
foreach (string dir in Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory))
{
try
{
//see if this directory corresponds to a valid culture name
DirectoryInfo dirinfo = new DirectoryInfo(dir);
tCulture = CultureInfo.GetCultureInfo(dirinfo.Name);
//determine if a resources dll exists in this directory that matches the executable name
string exe = System.Reflection.Assembly.GetExecutingAssembly().Location;
if (dirinfo.GetFiles(Path.GetFileNameWithoutExtension(exe) + ".resources.dll").Length > 0)
{
pSupportedCultures.Add(tCulture);
Debug.WriteLine(string.Format(" Found Culture: {0} [{1}]", tCulture.DisplayName, tCulture.Name));
}
}
catch (ArgumentException) //ignore exceptions generated for any unrelated directories in the bin folder
{
}
}
bFoundInstalledCultures = true;
}
}
/// <summary>
/// The Resources ObjectDataProvider uses this method to get
/// an instance of the _This Application Namespace_.Properties.Resources class
/// </summary>
public Properties.Resources GetResourceInstance()
{
return new Properties.Resources();
}
public static ObjectDataProvider ResourceProvider
{
get
{
if (provider == null)
provider = (ObjectDataProvider)App.Current.FindResource("Resources");
return provider;
}
}
/// <summary>
/// Change the current culture used in the application.
/// If the desired culture is available all localized elements are updated.
/// </summary>
/// <param name="culture">Culture to change to</param>
public static void ChangeCulture(CultureInfo culture)
{
// Remain on the current culture if the desired culture cannot be found
// - otherwise it would revert to the default resources set, which may or may not be desired.
if (pSupportedCultures.Contains(culture))
{
Properties.Resources.Culture = culture;
ResourceProvider.Refresh();
RaiseCultureUpdateEvent(null, new EventArgs());
Debug.WriteLine(string.Format("Culture changed to [{0}].", culture.NativeName));
}
else
{
Debug.WriteLine(string.Format("Culture [{0}] not available", culture));
}
}
private static void RaiseCultureUpdateEvent(object sender, EventArgs e)
{
EventHandler<EventArgs> handleit = CultureUpdateEvent;
CultureUpdateEvent?.Invoke(sender, e);
}
}
}
拼图的最后一块应该是提供对来自 xaml 的文化资源的访问的方法。这是使用 ObjectDataProvider 完成的。
您可以直接将其放入 App.xaml 或单独的文件中并在 App.xaml 中引用它。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Cultures="clr-namespace:Multi_Language_Base_App.Cultures">
<!-- Contains the current instance of the ProjectName.Properties.Resources class.
Used in bindings to get localized strings and automatic updates when the culture is updated -->
<ObjectDataProvider x:Key="Resources"
ObjectType="{x:Type Cultures:CultureResources}"
MethodName="GetResourceInstance"/>
<!-- Provides access to list of currently available cultures -->
<ObjectDataProvider x:Key="CultureResourcesDS"
ObjectType="{x:Type Cultures:CultureResources}"/>
</ResourceDictionary>
执行此操作时,您的字符串绑定可以从一开始就自动匹配系统区域性(或者最终成为通用资源中的默认值)。用户还可以即时切换文化。
在您的示例中,ComboBox SelectionChanged 事件将用作改变区域性的起点,如下所示:
CultureInfo CultureJapanese = new CultureInfo("ja-JP");
Cultures.CultureResources.ChangeCulture(CultureJapanese);
我更喜欢使用命令来完成这件事,但这取决于你。