Saltar al contenido
Localizar nombres de propiedades, descripciones y categorías para XamPropertyGrid

Localizar nombres de propiedades, descripciones y categorías para XamPropertyGrid

Quería ver si podía adaptar mi entrada de blog sobre cómo localizar descripciones de enumeración en WPF para dar cabida a xamPropertyGrid, pero ir un poco más allá localizando también DisplayName y Category.

4min read

El otro día estaba navegando por los foros de WPF de Infragistics y me encontré con esta pregunta que preguntaba cómo localizar las descripciones de las propiedades en el control xamPropertyGrid.

El póster original analizaba otras soluciones, incluido el uso de atributos, pero pensaba que esas soluciones eran demasiado complicadas y no muy sencillas.  Por supuesto, mi primer pensamiento fue "entonces hay que hacerlo mal".  Así que quería ver si podía adaptar mi entrada de blog sobre cómo localizar descripciones de enumeración en WPF para dar cabida a xamPropertyGrid, pero ir un poco más allá localizando también DisplayName y Category.  Quiero decir, diablos, estamos en una cuadrícula de propiedades con mucha información de propiedades, ¿por qué localizar solo la descripción?  Diablos no, ¡localizémoslo todo!

Adición de compatibilidad con la localización

Mi primer paso fue usar mi LocalizedDescriptionAttribute "as-is" de mi otra publicación para ver si simplemente funcionaba.  Así que simplemente copié y pegué esta clase en mi proyecto.

public class LocalizedDescriptionAttribute : DescriptionAttribute
{
    readonly ResourceManager _resourceManager;
    readonly string _resourceKey;

    public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
    {
        _resourceManager = new ResourceManager(resourceType);
        _resourceKey = resourceKey;
    }

    public override string Description
    {
        get
        {
            string description = _resourceManager.GetString(_resourceKey);
            return string.IsNullOrWhiteSpace(description) ? string.Format("[[{0}]]", _resourceKey) : description;
        }
    }
}

Ahora, quería agregar soporte para DisplayName y para Category de las propiedades.  Así que creé otras dos clases que usaban un enfoque muy similar al que usé para LocalizedDescriptionAttribute.

El LocalizedDisplayNameAttribute tiene un aspecto casi idéntico.

public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
    readonly ResourceManager _resourceManager;
    readonly string _resourceKey;

    public LocalizedDisplayNameAttribute(string resourceKey, Type resourceType)
    {
        _resourceManager = new ResourceManager(resourceType);
        _resourceKey = resourceKey;
    }

    public override string DisplayName
    {
        get
        {
            string displayName = _resourceManager.GetString(_resourceKey);
            return string.IsNullOrWhiteSpace(displayName) ? string.Format("[[{0}]]", _resourceKey) : displayName;
        }
    }
}

Sin embargo, LocalizedCategoryAttribute tiene una ligera modificación.  Tuve que invalidar el método GetLocalizedString.  Aparte de eso, la lógica es la misma.

public class LocalizedCategoryAttribute : CategoryAttribute
{
    readonly ResourceManager _resourceManager;
    readonly string _resourceKey;

    public LocalizedCategoryAttribute(string resourceKey, Type resourceType)
    {
        _resourceManager = new ResourceManager(resourceType);
        _resourceKey = resourceKey;
    }

    protected override string GetLocalizedString(string value)
    {
        string category = _resourceManager.GetString(_resourceKey);
        return string.IsNullOrWhiteSpace(category) ? string.Format("[[{0}]]", _resourceKey) : category;
    }
}

Ahora podemos seguir adelante y agregar un par de archivos Resource.resx al proyecto y dirigirnos a las referencias culturales que deseemos.  Estoy apoyando el inglés y el japonés (Nihongo).

Recursos de la persona

PersonResources.resx(Inglés)

Recursos para personas en inglés

PersonResources.ja-JP.resx (Japanese)

Recursos para personas japonesas

Dado que tenemos recursos, necesitamos algunas propiedades para comenzar a localizar.  Lo mantendré simple y solo usaré una clase Person con una sola propiedad.

public class Person
{
    [LocalizedDisplayName("NameDisplayName", typeof(PersonResources))]
    [LocalizedDescription("NameDescription", typeof(PersonResources))]
    [LocalizedCategory("PersonCategory", typeof(PersonResources))]
    public string Name { get; set; }
}

Ejecutemos nuestra aplicación y veamos qué tenemos.  El valor predeterminado serán nuestros recursos en inglés.  Esto significa que todos los valores que se muestran se recuperan del archivo PersonResources.resx.

xamPropertGrid localized with English

¿Qué sucede cuando queremos cambiar para usar nuestros valores localizados en japonés?  Bueno, vamos a averiguarlo.  Abra su App.xaml.cs y anule el método de inicio y cambie la cultura.

protected override void OnStartup(StartupEventArgs e)
{
    CultureInfo info = new CultureInfo("ja-JP");
    Thread.CurrentThread.CurrentCulture = info;
    Thread.CurrentThread.CurrentUICulture = info;
}

Now, run the applications again.

xamPropertyGrid localized with Japanese

¡Funciona a las mil maravillas!  Es obvio que nuestros valores se recuperan de nuestros recursos japoneses almacenados en el archivo PersonResources.ja-JA.resx.

Bastante hábil, ¿verdad?  No creo que esto sea demasiado complicado o difícil de seguir en absoluto.  A mí me parece bastante sencillo.  ¿Qué te parece?  Con suerte, esto le resultará útil y tal vez incluso use este enfoque en sus aplicaciones de WPF.  Asegúrate de revisar el código fuente y comienza a jugar con él.  Como siempre, no dudes en ponerte en contacto conmigo en mi blog, conéctate conmigo en Twitter (@brianlagunas) o deja un comentario a continuación para cualquier pregunta o comentario que puedas tener.

Solicitar una demostración