68 votes

Obtenir des valeurs à partir de fichiers *.resx dans XAML

Est-il possible d'ajouter une valeur provenant d'un fichier de ressources directement dans le balisage XAML ? Ou pour la localisation, nous devons toujours faire quelque chose comme ça dans le fichier *.cs :

txtMessage.Text = Messages.WarningUserMessage;

Messages est une ressource, et txtMessage est TextBlock.

79voto

Julien Lebosquain Points 20894

Assurez-vous que la génération de code est réglée sur Public dans l'éditeur resx, puis vous pouvez simplement utiliser :

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

62voto

Daniex Points 111

Il est beaucoup plus facile de procéder de cette manière. Ajouter un xmlns dans le fichier XAML et utiliser les ressources directement.

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

14voto

Yogs Points 141

Je comprends que ma réponse est un peu tardive, mais j'ai pensé qu'elle valait la peine d'être partagée :

Pour utiliser une chaîne de caractères stockée dans le fichier *.resx sans le mot-clé Static :

  1. Dans le fichier App.Xaml, ajouter un espace de noms pour les propriétés xmlns:resource="clr-namespace:YourProject.Properties"

  2. Dans ApplicationResources (fichier app.xaml), ajoutez une ressource pour votre fichier *.resx.

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

  3. Dans votre fichier XAML, utilisez le Binding suivant, prenons l'exemple du Titre de la fenêtre

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

    TitleString est le nom de StringProperty dans votre fichier *.resx

  4. Enfin, n'oubliez pas de modifier le modificateur d'accès au fichier de ressources en Public.

5voto

Steven Robbins Points 18791

La manière la plus simple est probablement de référencer les éléments directement (ce sont des propriétés statiques, internes par défaut) :

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

Si vous travaillez sur une application WPF localisée, je vous recommande de jeter un coup d'œil sur les conseils de CodePlex à l'adresse suivante http://wpflocalization.codeplex.com/ et si vous construisez une application composite (utilisant PRISM ou MEF), j'ai une solution pour vous. billet de blog sur une bonne façon de réaliser la localisation WPF en utilisant des bindings standards .

2voto

user3318309 Points 41

Après une journée entière d'enquête, ce commentaire Localisation de Xaml : Utilisation de ressources .resx en Xaml sans x:static J'ai trouvé une solution simple pour fournir un support multilangue avec les fichiers *.resx (ressources intégrées ou assemblages référencés). Depuis Framework 4, il existe une classe de base appelée DynamicObject pour spécifier le comportement dynamique au moment de l'exécution dans l'espace de noms System.Dynamic.

J'ai dérivé le ResourceLoader suivant de la classe System.Dynamic.DynamicObject :

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
}

Vous pouvez créer une instance au sein de xaml comme suit :

<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>

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;                      
    }       
}

Il est maintenant possible de lier des chaînes et des images (les images seront converties en BitmapSource WPF compilant :

    <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>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X