Szukam sposobu na zlokalizowanie nazw właściwości wyświetlanych w PropertyGrid. Nazwę właściwości można „nadpisać” przy użyciu atrybutu DisplayNameAttribute. Niestety atrybuty nie mogą mieć wyrażeń innych niż stałe. Nie mogę więc używać silnie wpisanych zasobów, takich jak:
class Foo
{
[DisplayAttribute(Resources.MyPropertyNameLocalized)] // do not compile
string MyProperty {get; set;}
}
Rozejrzałem się i znalazłem sugestię, aby dziedziczyć po DisplayNameAttribute, aby móc korzystać z zasobów. Skończyłbym z kodem takim jak:
class Foo
{
[MyLocalizedDisplayAttribute("MyPropertyNameLocalized")] // not strongly typed
string MyProperty {get; set;}
}
Jednak tracę mocno wpisane korzyści związane z zasobami, co zdecydowanie nie jest dobrą rzeczą. Potem natknąłem się na DisplayNameResourceAttribute, który może być tym, czego szukam. Ale ma znajdować się w przestrzeni nazw Microsoft.VisualStudio.Modeling.Design i nie mogę znaleźć odniesienia, które mam dodać do tej przestrzeni nazw.
Czy ktoś wie, czy istnieje łatwiejszy sposób na osiągnięcie lokalizacji DisplayName w dobry sposób? lub jeśli istnieje sposób wykorzystania tego, co wydaje się być używane przez firmę Microsoft w programie Visual Studio?
źródło
Odpowiedzi:
Istnieje atrybut Display z System.ComponentModel.DataAnnotations w .NET 4. Działa na MVC 3
PropertyGrid
.To wyszukuje zasób nazwany
UserName
w twoimMyResources
pliku resx.źródło
typeof(MyResources)
, może być konieczne ustawienie modyfikatora dostępu do pliku zasobów na Publiczny .Robimy to dla wielu atrybutów, aby obsługiwać wiele języków. Podjęliśmy podobne podejście do firmy Microsoft, w której zastępują one swoje podstawowe atrybuty i przekazują nazwę zasobu zamiast rzeczywistego ciągu. Nazwa zasobu jest następnie używana do wyszukiwania w zasobach DLL w celu zwrócenia rzeczywistego ciągu.
Na przykład:
Możesz pójść o krok dalej, gdy faktycznie używasz atrybutu i określić nazwy zasobów jako stałe w klasie statycznej. W ten sposób otrzymasz deklaracje typu.
Aktualizacja
ResourceStrings
wyglądałaby mniej więcej tak (uwaga, każdy ciąg odnosiłby się do nazwy zasobu, który określa rzeczywisty ciąg):źródło
[MyNamespace].[MyResourceFile].ResourceManager.GetString("MyString");
Oto rozwiązanie, które znalazłem w osobnym zestawie (zwanym w moim przypadku „wspólnym”):
z kodem do wyszukania zasobu:
Typowe użycie to:
Co jest dość brzydkie, ponieważ używam literalnych ciągów jako klucza zasobów. Używanie stałej oznaczałoby modyfikację Resources.Designer.cs, co prawdopodobnie nie jest dobrym pomysłem.
Wniosek: nie jestem z tego zadowolony, ale jeszcze mniej cieszy mnie Microsoft, który nie jest w stanie zapewnić niczego przydatnego do tak powszechnego zadania.
źródło
ResourceManager
właściwości. Zamiast tego możesz po prostu pobrać nieruchomość bezpośrednio z typu podanego w parametrze:PropertyInfo property = resourceManagerProvider.GetProperty(resourceKey, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Używając atrybutu Display (z System.ComponentModel.DataAnnotations) i wyrażenia nameof () w C # 6, otrzymasz zlokalizowane i silnie wpisane rozwiązanie.
źródło
Możesz użyć T4 do wygenerowania stałych. Napisałem jeden:
źródło
To stare pytanie, ale myślę, że jest to bardzo powszechny problem, a oto moje rozwiązanie w MVC 3.
Po pierwsze, szablon T4 jest potrzebny do generowania stałych, aby uniknąć nieprzyjemnych ciągów znaków. Mamy plik zasobów „Labels.resx” zawierający wszystkie ciągi etykiet. Dlatego szablon T4 używa bezpośrednio pliku zasobów,
Następnie zostaje utworzona metoda rozszerzenia, aby zlokalizować „DisplayName”,
Atrybut „DisplayName” zostaje zastąpiony atrybutem „DisplayLabel” w celu automatycznego odczytu z „Labels.resx”,
Po tych wszystkich przygotowaniach czas na dotknięcie domyślnych atrybutów walidacji. Jako przykładu używam atrybutu „Wymagane”,
Teraz możemy zastosować te atrybuty w naszym modelu,
Domyślnie nazwa właściwości jest używana jako klucz do wyszukiwania „Label.resx”, ale jeśli ustawisz ją za pomocą „DisplayLabel”, użyje go zamiast tego.
źródło
Możesz podklasę DisplayNameAttribute, aby zapewnić i18n, zastępując jedną z metod. Tak, tak. edycja: Być może będziesz musiał zadowolić się użyciem stałej dla klucza.
źródło
W moim przypadku używam tego rozwiązania
Z kodem
źródło
Cóż, montaż jest
Microsoft.VisualStudio.Modeling.Sdk.dll
. który jest dostarczany z Visual Studio SDK (z pakietem integracyjnym Visual Studio).Ale byłby używany w mniej więcej taki sam sposób, jak twój atrybut; nie ma możliwości użycia silnie typów zasobów w atrybutach tylko dlatego, że nie są one stałe.
źródło
Przepraszam za kod VB.NET, mój C # jest trochę zardzewiały ... Ale zrozumiesz, o co chodzi, prawda?
Przede wszystkim utwórz nową klasę
LocalizedPropertyDescriptor
:, która dziedziczyPropertyDescriptor
. ZastąpDisplayName
właściwość w następujący sposób:Some.ResourceManager
to ResourceManager pliku zasobów, który zawiera tłumaczenia.Następnie zaimplementuj
ICustomTypeDescriptor
w klasie ze zlokalizowanymi właściwościami i zastąpGetProperties
metodę:Możesz teraz użyć atrybutu „DisplayName” do przechowywania odniesienia do wartości w pliku zasobów ...
prop_description
jest kluczem w pliku zasobów.źródło