gpt4 book ai didi

c# - 在 MVVM : is it good to reference the resources from the ViewModel? 中本地化对话框

转载 作者:行者123 更新时间:2023-12-03 10:28:32 25 4
gpt4 key购买 nike

我已经到了需要向我的 WPF MVVM 应用程序添加本地化的地步(我使用 Caliburn.Micro + Autofac)。

我做了一些研究,发现了许多不同的方法来完成它,但没有一个提供本地化对话文本的解决方案。
作为对话框,我使用具有 Caption 和 Message 字符串属性的 DialogViewModel,并使用 CM 的 WindowManager 在 DialogView 中显示它。
我有自动取款机是这样的

this.windowManager.ShowDialog(new DialogViewModel("Hello!", "Hello everybody!!"))

但也像
this.windowManager.ShowDialog(new DialogViewModel("Hello!", "Hello " + this.Name + "!!"))

我以为我可以使用像 "Hello {0}!!" 这样的资源字符串并以这种方式使用它
this.windowManager.ShowDialog(new DialogViewModel("Hello!", string.Format(languageResources.HelloName, this.Name)))

从 ViewModel 层引用本地化资源好不好?

最佳答案

资源是使用 View 的数据,我认为不建议从 ViewModel 引用资源。另一方面,如果它是一个存储特定字符串的类(可能是静态的),并且对 View 一无所知,那么它将是一些可以在 ViewModel 中的抽象。在任何情况下,您都应该尝试使用我将提供的技术或任何其他技术来处理 View 上的资源。

Using x:Static Member

在 WPF 中,可以像这样绑定(bind)来自类的静态数据:

<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 中使用(带有预定义的接口(interface))。您可以定义一个附加属性,其中属性处理程序可以访问元素及其资源。

实现附加行为的示例,见下文:

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

关于c# - 在 MVVM : is it good to reference the resources from the ViewModel? 中本地化对话框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21559870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com