2010-05-27 16 views
51

¿Es posible agregar algún valor del archivo de recursos directamente en el marcado XAML? O para la localización siempre tenemos que hacer algo como esto en el archivo .cs *:Obtenga valores de los archivos * .resx en XAML

txtMessage.Text = Messages.WarningUserMessage; 

Dónde Messages es de recursos, y txtMessage es TextBlock.

+1

¿Cómo se creó el archivo de recursos de Mensajes? ¿Acabas de agregar Messages.resx a tu carpeta de propiedades? Si es así, no puedo acceder a este archivo. – Sergey

+0

@Sergey, sin importar dónde se encuentre. Claro que también puedes agregarlo a la carpeta de propiedades. El archivo Sure Resx debe estar en el directorio del proyecto. ¿Puede ser que no puedes agregarlo al directorio de propiedades de VS? Por cierto, es una mala práctica agregar smth al directorio de propiedades. Mejor crea el directorio de "recursos" para mantener tus archivos de res. – 0x49D1

Respuesta

59

asegurarse de que la generación de código se establece en público en el editor resx, a continuación, puede simplemente usar:

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

¡Soy nuevo en WPF y esta es la respuesta que necesitaba! Gracias. – 0x49D1

+0

Tenga en cuenta que solo funciona si 'Messages' está en el mismo espacio de nombres que la pantalla. –

+3

... y si 'Messages' no está en un ensamblaje diferente ya que el constructor se genera como interno. –

5

La forma más sencilla es probablemente para hacer referencia a los artículos directamente (son propiedades estáticas, internos por defecto):

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

Si está trabajando en una aplicación WPF localizada embargo, te recomiendo echar un vistazo a la guía en CodePlex en http://wpflocalization.codeplex.com/, y si usted está construyendo una aplicación compuesta (usando PRISM o MEF) entonces tengo un blog post on a nice way to accomplish WPF localisation using standard bindings.

53

Es mucho más fácil hacerlo así. Agregue un xmlns en el archivo XAML y use los recursos directamente.

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

El único inconveniente de este enfoque es, por supuesto, que no se puede cambiar la cultura de forma dinámica. Hay un gran artículo sobre cómo lograr ese comportamiento mediante el uso de una extensión de marcado y un administrador de localización en alguna parte. –

+4

aquí está: http://www.grumpydev.com/2009/09/08/localising-wpf-applications-using-resx-files-and-standard-data-binding-without-a-markupextension/ –

1

Después de una investigación de todo el día este comentario Xaml localization: Using .resx Resources in Xaml without x:static he encontrado una solución sencilla para proporcionar soporte multilenguaje con (recursos incrustados o ensamblaje de referencia) * .resx - archivos. Desde Framework 4 hay una clase base llamada DynamicObject para especificar el comportamiento dinámico en tiempo de ejecución en el espacio de nombres System.Dynamic.

que obtendrá según ResourceLoader de System.Dynamic.DynamicObject - clase:

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 
} 

Usted puede crear instancia dentro xaml así:

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

Ahora es posible enlazar las cadenas y las imágenes (las imágenes se convierten en WPF BitmapSource 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> 
8

entiendo mi respuesta es un poco tarde, pero me pareció que el intercambio de la pena:

al usuario A cadena almacenada en el archivo * .resx sin palabra clave estática:

  1. en archivo App.xaml añadir un espacio de nombres para las propiedades xmlns:resource="clr-namespace:YourProject.Properties"
  2. En ApplicationResources (archivo app.xaml) Agregue un recurso para su *.resx

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

  3. En su archivo XAML utilizar la continuación de la unión, permite echar un ejemplo de título de la ventana

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

    títuloCadena es el nombre de StringProperty en su archivo * .resx

  4. Por último, pero no menos importante, no olvides cambiar el modificador de acceso a archivos de recursos a Público.

Enjoy :)

+0

Cómo lo hizo haces que esto funcione? Seguí exactamente sus instrucciones, pero el archivo de recursos (con un modificador de acceso público configurado en 'Public') creado básicamente contiene una clase estática con un constructor protegido. Tanto en WPF como en Metro, aparece el error 'el tipo ResourceFileName no incluye constructores accesibles' en el diseñador XAML (y otro error similar cuando se compila). –

+0

Exactamente, el mismo error que se menciona arriba. – Hekkaryk

-1

ocultar un bloque de texto y otros se unen es el texto En ese bloque de texto que tendrá el recurso de Cs

0

la forma más sencilla, donde se puede definir el ancho de cuadro de texto también de acuerdo con la longitud del texto en cada idioma.

Código Xaml

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

recurso de archivo: -

Nombre - Valor

Greeting.Text - Hola

Greeting.width - 20

Have a look at resource file:- Click View

+0

Formatee su código como tal, ingrese 4 espacios al frente para todas las filas de código. – Luuklag

Cuestiones relacionadas