简体   繁体   English

从XAML中的* .resx文件中获取值

[英]Get values from *.resx files in XAML

Is it possible to add some value from resource file right into the XAML markup? 是否可以将资源文件中的某些值添加到XAML标记中? Or for localization we always have to make something like this in *.cs file: 或者对于本地化,我们总是要在* .cs文件中制作这样的东西:

txtMessage.Text = Messages.WarningUserMessage;

Where Messages is resource, and txtMessage is TextBlock. 其中Messages是资源, txtMessage是TextBlock。

确保在resx编辑器中将Code Generation设置为Public,然后您可以简单地使用:

<TextBlock Text="{x:Static Messages.WarningUserMessage}" />

It's a lot easier to do it like this. 这样做要容易得多。 Add a xmlns in XAML file and use the resources directly. 在XAML文件中添加xmlns并直接使用资源。

xmlns:resx="clr-namespace:wpfapplicationname.Properties"
Title="{x:Static resx:Resources.name}"

I understand my reply is a bit late, but I thought its worth sharing: 我知道我的回复有点迟了,但我认为值得分享:

To use a string stored in the *.resx file without Static keyword: 要使用存储在* .resx文件中的字符串而不使用Static关键字:

  1. In App.Xaml file add a namespace for Properties xmlns:resource="clr-namespace:YourProject.Properties" 在App.Xaml文件中为Properties xmlns:resource="clr-namespace:YourProject.Properties"添加命名空间xmlns:resource="clr-namespace:YourProject.Properties"
  2. In ApplicationResources(app.xaml file) Add a Resource for your *.resx file 在ApplicationResources(app.xaml文件)中为您的* .resx文件添加资源

    <Application.Resources> <resource:ResourceFileName x:Key="ApplicationStringResources" /> </Application.Resources>

  3. In your XAML file use the following Binding, let us take an example of Window Title 在您的XAML文件中使用以下Binding,让我们以Window Title为例

    Title="{Binding TitleString, Source={StaticResource ResourceKey=ApplicationStringResources}}"

    TitleString is the name of StringProperty in your *.resx file TitleString是* .resx文件中StringProperty的名称

  4. Last but not least, don't forget to change the resource file access modifier to Public. 最后但并非最不重要的是,不要忘记将资源文件访问修饰符更改为Public。

The simplest way is probably to reference the items directly (they are static properties, internal by default): 最简单的方法可能是直接引用项目(它们是静态属性,默认为内部):

<TextBlock x:Name="txtMessage" Text="{x:Static MyApp.Properties.Resource.TextString}"/>

If you are working on a localised WPF app though then I'd recommend taking a look at the guidance on CodePlex at http://wpflocalization.codeplex.com/ , and if you're building a composite app (using PRISM or MEF) then I have a blog post on a nice way to accomplish WPF localisation using standard bindings . 如果您正在使用本地化的WPF应用程序,那么我建议您在http://wpflocalization.codeplex.com/上查看有关CodePlex的指南,如果您正在构建复合应用程序(使用PRISM或MEF)然后我有一篇关于使用标准绑定完成WPF本地化的好方法博客文章

After a whole day investigation this Comment Xaml localization: Using .resx Resources in Xaml without x:static I found a simple solution to provide multilanguage support with (embedded resources or referenced assembly) *.resx - files. 经过一整天的调查,这个评论Xaml本地化:在Xaml中使用.resx资源而不使用x:static我找到了一个简单的解决方案来提供多语言支持(嵌入式资源或引用程序集)* .resx - 文件。 Since Framework 4 there is a base class called DynamicObject for specifying dynamic behavior at run time in namespace System.Dynamic. 从Framework 4开始,有一个名为DynamicObject的基类,用于在命名空间System.Dynamic中指定运行时的动态行为。

I derived following ResourceLoader from System.Dynamic.DynamicObject - class: 我从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
}

You can create instance within xaml like this: 您可以在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# code: 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;                      
    }       
}

Now it is possible to bind strings and images (images will be converted into WPF compilant BitmapSource: 现在可以绑定字符串和图像(图像将转换为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>

The simplest way, where you can define the width of textbox also according to the length of text in each language. 最简单的方法,您还可以根据每种语言的文本长度定义文本框的宽度。

Xaml Code Xaml代码

<TextBlock x:Uid="Greeting" Text="" />

Have a look at resource file:- Click View 查看资源文件: - 单击“查看”

隐藏其他文本块并绑定它的文本在该文本块中,您将拥有来自.cs的资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM