Resources 是使用View 的数据,我认为不建议从ViewModel 引用资源。另一方面,如果它是一个存储特定字符串的类(可能是静态的),并且对View 一无所知,那么它将是一些可以在ViewModel 中的抽象。在任何情况下,您都应该尝试使用我将提供的技术或任何其他技术来使用View 方面的资源。
Using x:Static Member
在 WPF 中,可以像这样绑定类中的静态数据:
<x:Static Member="prefix : typeName . staticMemberName" .../>
下面是格式字符串在一个类中的示例,用于显示日期和时间的格式。
XAML
xmlns:local="clr-namespace:YourNameSpace"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
<Grid>
<TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat={x:Static Member=local:StringFormats.DateFormat}}"
HorizontalAlignment="Right" />
<TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}, StringFormat={x:Static Member=local:StringFormats.Time}}" />
</Grid>
Code behind
public class StringFormats
{
public static string DateFormat = "Date: {0:dddd}";
public static string Time = "Time: {0:HH:mm}";
}
在这种情况下,StringFormats 类被视为资源,尽管它实际上是一个普通类。更多信息请见x:Static Markup Extension on MSDN。
Using Converter
如果你有存储在Application.Current.Resources中的资源,并且需要添加一些逻辑,这种情况下,你可以使用转换器。这个例子取自here:
XAML
<Button Content="{Binding ResourceKey, Converter={StaticResource resourceConverter}}" />
Code behind
public class StaticResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var resourceKey = (string)value;
// Here you can add logic
return Application.Current.Resources[resourceKey];
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
Note: 在转换器中,最好不要使用重逻辑,因为它会影响性能。更复杂的逻辑见下文。
Attached Behavior
当没有x:Static Member 并且转换器没有帮助时,应将附加行为用于具有视觉元素的复杂操作。附加行为是非常强大和方便的解决方案,完全满足 MVVM 模式,也可以在 Blend 中使用(带有预定义的接口)。您可以定义一个附加属性,其中属性处理程序可以访问元素及其资源。
实施附加行为示例,见下文:
Set focus to a usercontrol when it is made visible
Animated (Smooth) scrolling on ScrollViewer
Setting WindowStartupLocation from ResourceDictionary throws XamlParseException
Example with converter
App.xaml
我在这里存储每种文化的字符串。
<Application x:Class="MultiLangConverterHelp.App"
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"
StartupUri="MainWindow.xaml">
<Application.Resources>
<sys:String x:Key="HelloStringEN">Hello in english!</sys:String>
<sys:String x:Key="HelloStringRU">Привет на русском!</sys:String>
</Application.Resources>
</Application>
MainWindow.xaml
输入是当前的文化,可以在转换器中获得,为了简单起见,我这样做了。
<Window x:Class="MultiLangConverterHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MultiLangConverterHelp"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:StaticResourceConverter x:Key="converter" />
<local:TestViewModel x:Key="viewModel" />
</Window.Resources>
<Grid DataContext="{StaticResource viewModel}">
<TextBlock Text="{Binding Path=CurrentCulture, Converter={StaticResource converter}}" />
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class StaticResourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var currentCulture = (string)value;
if (currentCulture.Equals("EN-en"))
{
return Application.Current.Resources["HelloStringEN"];
}
else if (currentCulture.Equals("RU-ru"))
{
return Application.Current.Resources["HelloStringRU"];
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
public class TestViewModel : NotificationObject
{
private string _currentCulture = "EN-en";
public string CurrentCulture
{
get
{
return _currentCulture;
}
set
{
_currentCulture = value;
NotifyPropertyChanged("CurrentCulture");
}
}
}
另外,我建议你学习更简单的方法,这些方法已经在 WPF 技术中:
WPF Localization for Dummies
WPF Globalization and Localization Overview