Localizar nomes de propriedade, descrições e categorias para o XamPropertyGrid
Eu queria ver se poderia adaptar minha postagem no blog sobre como localizar descrições de enumeração no WPF para acomodar o xamPropertyGrid, mas ir um pouco mais longe, localizando também o DisplayName e a Categoria.
Eu estava navegando nos fóruns do Infragistics WPF outro dia e me deparei com esta pergunta perguntando como localizar as descrições das propriedades no controle xamPropertyGrid.
O pôster original analisou outras soluções, incluindo o uso de atributos, mas achou que essas soluções eram excessivamente complicadas e não muito diretas. Claro que meu primeiro pensamento foi "então estão fazendo errado". Então, eu queria ver se eu poderia adaptar minha postagem no blog sobre como localizar descrições de enumeração no WPF para acomodar o xamPropertyGrid, mas ir um pouco mais longe, localizando também o DisplayName e a Categoria. Quero dizer, diabos, estamos em uma grade de propriedades com muitas informações de propriedade, por que localizar apenas a descrição? Caramba, não, vamos localizar tudo!
Adicionando suporte à localização
Meu primeiro passo foi usar meu LocalizedDescriptionAttribute "como está" do meu outro post para ver se funcionaria. Então, eu apenas copiei e colei essa classe no meu projeto.
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; } } }
Agora, eu queria adicionar suporte para o DisplayName e para a Categoria das propriedades. Então, criei duas outras classes que usavam uma abordagem muito semelhante à que usei para o LocalizedDescriptionAttribute.
O LocalizedDisplayNameAttribute parece quase 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; } } }
Mas, o LocalizedCategoryAttribute tem uma pequena modificação. Tive que substituir o método GetLocalizedString. Fora isso, a lógica é a mesma.
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; } }
Agora podemos adicionar alguns arquivos Resource.resx ao projeto e direcionar as culturas desejadas. Estou apoiando inglês e japonês (Nihongo).

PersonResources.resx(Inglês)

PersonResources.ja-JP.resx (Japanese)

Como temos recursos, precisamos de algumas propriedades para começar a localizar. Vou mantê-lo simples e usar apenas uma classe Person com uma única propriedade.
public class Person { [LocalizedDisplayName("NameDisplayName", typeof(PersonResources))] [LocalizedDescription("NameDescription", typeof(PersonResources))] [LocalizedCategory("PersonCategory", typeof(PersonResources))] public string Name { get; set; } }
Vamos executar nosso aplicativo e ver o que temos. O padrão serão nossos recursos em inglês. Isso significa que todos os valores exibidos estão sendo recuperados do arquivo PersonResources.resx.

O que acontece quando queremos mudar para usar nossos valores localizados em japonês? Bem, vamos descobrir. Abra seu App.xaml.cs e substitua o método de inicialização e mude a 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.

Funciona como um encanto! É óbvio que nossos valores estão sendo recuperados de nossos recursos japoneses armazenados no arquivo PersonResources.ja-JA.resx.
Muito liso, certo? Não acho que isso seja complicado demais ou difícil de seguir. Parece muito direto para mim. O que você acha? Espero que você ache isso útil e talvez até use essa abordagem em seus aplicativos WPF. Certifique-se de verificar o código-fonte e começar a brincar com ele. Como sempre, sinta-se à vontade para entrar em contato comigo no meu blog, conecte-se comigo no Twitter (@brianlagunas) ou deixe um comentário abaixo para quaisquer perguntas ou comentários que possa ter.