是否可以将资源文件中的一些值直接添加到 XAML 标记中?或者为了本地化,我们总是必须在 *.cs 文件中制作类似的内容:
txtMessage.Text = Messages.WarningUserMessage;
其中
Messages
是资源,txtMessage
是 TextBlock。
确保在 resx 编辑器中将代码生成设置为 Public,然后您可以简单地使用:
<TextBlock Text="{x:Static Messages.WarningUserMessage}" />
这样做就容易多了。在XAML文件中添加一个xmlns并直接使用资源。
xmlns:resx="clr-namespace:wpfapplicationname.Properties"
Title="{x:Static resx:Resources.name}"
我知道我的回复有点晚了,但我认为它值得分享:
要使用存储在 *.resx 文件中且不带 Static 关键字的字符串:
xmlns:resource="clr-namespace:YourProject.Properties"
在ApplicationResources(app.xaml文件)中为您的*.resx文件添加资源
<Application.Resources>
<resource:ResourceFileName x:Key="ApplicationStringResources" />
</Application.Resources>
在您的 XAML 文件中使用以下绑定,让我们以窗口标题为例
Title="{Binding TitleString, Source={StaticResource ResourceKey=ApplicationStringResources}}"
TitleString 是 *.resx 文件中 StringProperty 的名称
最后但并非最不重要的一点是,不要忘记将资源文件访问修饰符更改为 Public。
最简单的方法可能是直接引用项目(它们是静态属性,默认为内部):
<TextBlock x:Name="txtMessage" Text="{x:Static MyApp.Properties.Resource.TextString}"/>
如果您正在开发本地化的 WPF 应用程序,那么我建议您查看 http://wpflocalization.codeplex.com/ 上的 CodePlex 指南,并且如果您正在构建复合应用程序(使用 PRISM或 MEF),那么我有一篇 博客文章,介绍了使用标准绑定完成 WPF 本地化的好方法。
经过一整天的调查此评论Xaml 本地化:在不带 x:static 的 Xaml 中使用 .resx 资源我找到了一个简单的解决方案,可以通过(嵌入资源或引用的程序集)*.resx - 文件提供多语言支持。 从 Framework 4 开始,有一个名为 DynamicObject 的基类,用于在命名空间 System.Dynamic 中指定运行时的动态行为。
我从 System.Dynamic.DynamicObject 派生了以下 ResourceLoader - 类:
public class ResourceLoader : DynamicObject
{
#region Fields ---------------------------------------------------------------
private const string DefaultResourcesSuffix = "Resource";
private ResourceManager _resourceMan;
private CultureInfo culture;
private readonly string _defaultAssemblyName;
private readonly Assembly _defaultAssembly;
private Assembly theAssembly;
private string resourcesSuffix;
private string assembly;
#endregion // Fields
#region Properties -----------------------------------------------------------
/// <summary>
/// Gets or sets the assembly.
/// </summary>
public string Assembly
{
get { return assembly; }
set
{
assembly = value;
theAssembly = System.Reflection.Assembly.Load(assembly);
_resourceMan = null;
}
}
/// <summary>
/// Gets or sets the resources suffix.
/// </summary>
public string ResourcesSuffix
{
get { return resourcesSuffix; }
set
{
resourcesSuffix = value;
_resourceMan = null;
}
}
/// <summary>
/// Get, set culture
/// </summary>
public CultureInfo CurrentCulture
{
get { this.culture = this.culture ?? CultureInfo.InvariantCulture; return this.culture; }
set { this.culture = value; }
}
/// <summary>
/// Creates new instace of <see cref="System.Resources.ResourceManager"/> at initialisation or change of <see cref="ResourceFileAccessSample.ResourceBinding.ResourceLoader.Assembly"/>.
/// </summary>
private ResourceManager ResourceManager
{
get
{
if (ReferenceEquals(_resourceMan, null))
{
ResourceManager temp = new ResourceManager(
string.Format("{0}.{1}", Assembly ?? _defaultAssemblyName, ResourcesSuffix ?? DefaultResourcesSuffix),
theAssembly ?? _defaultAssembly);
_resourceMan = temp;
}
return _resourceMan;
}
}
#endregion // Properties
#region Methods --------------------------------------------------------------
private object GetResource(string name, CultureInfo language)
{
if (language == null || language == CultureInfo.InvariantCulture)
return ResourceManager.GetObject(name);
return ResourceManager.GetObject(name, language);
}
/// <summary>
/// Provides the implementation for operations that get member values. Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can override this method to specify dynamic behavior for operations such as getting a value for a property.
/// </summary>
/// <param name="binder">Provides information about the object that called the dynamic operation. The binder.Name property provides the name of the member on which the dynamic operation is performed. For example, for the Console.WriteLine(sampleObject.SampleProperty) statement, where sampleObject is an instance of the class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Name returns "SampleProperty". The binder.IgnoreCase property specifies whether the member name is case-sensitive.</param>
/// <param name="result">The result of the get operation. For example, if the method is called for a property, you can assign the property value to <paramref name="result"/>.</param>
/// <returns>
/// true if the operation is successful; otherwise, false. If this method returns false, the run-time binder of the language determines the behavior. (In most cases, a run-time exception is thrown.)
/// </returns>
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = GetResource(binder.Name, this.culture);
if (result != null && result.GetType() == typeof(System.Drawing.Bitmap))
{
System.Drawing.Bitmap currentBmp = result as System.Drawing.Bitmap;
currentBmp.MakeTransparent(System.Drawing.Color.Magenta);
BitmapSource src = Imaging.CreateBitmapSourceFromHBitmap(currentBmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
result = src;
}
return result == null ? false : true;
}
/// <summary>
/// Switch set culture
/// </summary>
public void SwitchCulture(CultureInfo NewCulture)
{
this.culture = NewCulture;
}
#endregion // Methods
#region Constructors ---------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="ResourceLoader"/> class.
/// </summary>
public ResourceLoader()
: this(CultureInfo.InvariantCulture, DefaultResourcesSuffix)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="ResourceLoader"/> class.
/// </summary>
public ResourceLoader(CultureInfo InitCulture, string ResourceSuffix)
{
_defaultAssemblyName = GetType().Assembly.GetName().Name;
_defaultAssembly = GetType().Assembly;
this.culture = InitCulture;
this.resourcesSuffix = ResourceSuffix;
}
#endregion // Constructors
}
您可以像这样在 xaml 中创建实例:
<Application x:Class="ResourceFileAccessSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:ResourceFileAccessSample.ResourceBinding"
StartupUri="Window1.xaml" Startup="Application_Startup" >
<Application.Resources>
<src:ResourceLoader x:Key="resource" CurrentCulture="(Default)" ResourcesSuffix="Resource" />
</Application.Resources>
C#代码:
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
private ResourceLoader res;
public Window1()
{
InitializeComponent();
// load it from WPF Resources
this.res = (ResourceLoader)this.FindResource("resource");
// or create an instance
//this.res = new ResourceLoader(CultureInfo.InvariantCulture, "Resource");
this.LayoutRoot.DataContext = res;
}
private void btnSwichLanguage_Click(object sender, RoutedEventArgs e)
{
res.SwitchCulture(new CultureInfo("de"));
this.LayoutRoot.DataContext = null;
this.LayoutRoot.DataContext = res;
}
}
现在可以绑定字符串和图像(图像将转换为WPF兼容的BitmapSource:
<StackPanel Name="LayoutRoot" Orientation="Vertical">
<Label Name="lblText" Content="{Binding Path=rsName, Mode=OneWay}" HorizontalContentAlignment="Center" Margin="5" Padding="0" />
<Image Source="{Binding Path=AlignObjectsTop}" Height="16" Width="16" Margin="5" />
<Button Name="btnSwichLanguage" Content="Switch to de" Click="btnSwichLanguage_Click" MinHeight="25" Width="100" />
</StackPanel>
最简单的方法,您也可以根据每种语言的文本长度来定义文本框的宽度。
Xaml 代码
<TextBlock x:Uid="Greeting" Text="" />
隐藏其他文本块并绑定其文本 在该文本块中,您将获得 .cs 中的资源