Страницы

Поиск по вопросам

пятница, 28 июня 2019 г.

Странная ошибка в XAML: ошибка при конвертации типа при присваивании через StaticResource

Не знал как коротко описать суть проблемы.
Вот код xaml

Вот код c# класса LocalizedString
public class LocalizedString : IComparable, ICloneable, IEnumerable, IEquatable, IEquatable { public LocalizedString(string str) { OriginalString = str; }
public LocalizedString() { OriginalString = ""; }
public string OriginalString { get; set; }
public string LocalizeString { get { return InteractiveLocalizer.Localize(OriginalString); } }
public override string ToString() { return LocalizeString; }
public int CompareTo(object obj) { if (obj == null) return 1; var str = obj as string; if (str != null) return LocalizeString.CompareTo(str); var lstr = obj as LocalizedString; if (lstr != null) return LocalizeString.CompareTo(lstr.LocalizeString); throw new ArgumentException("LocalizedDtring: Bad type"); }
public object Clone() { return new LocalizedString(OriginalString); }
public IEnumerator GetEnumerator() { return LocalizeString.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public bool Equals(string other) { return other == LocalizeString || other == OriginalString; }
public bool Equals(LocalizedString other) { return OriginalString == other.OriginalString; }
public static implicit operator LocalizedString(string v) { return new LocalizedString(v); }
public static explicit operator String(LocalizedString ls) { return ls.LocalizeString; } }
В данном случае LocalizedString ворачивает ту же самую строку, что и получает "qwe". Я это и ожидал, но во время выполнения прога падает с исключением. Вот текст
"qwe" не является допустимым значением для свойства "Text".
Как так?
Ошибка есть и во время компиляции (хоть она и позволяет запуститься приложению). Вот ее текст
Не удается применить объект типа "LocalizerLib.LocalizedString" к свойству, для которого требуется тип "System.String".
В классе определены операторы implict и explict. Чего еще не хватает, чтобы я мог вместо string вставить свой тип?


Ответ

XAML игноирирует операторы приведения типа (хоть явные, хоть неявные). Разнообразные конвертеры используются, например, для преобразования результатов биндинга. И даже в этом случае операторы не используются, предпочтение отдаётся ассоциированному TypeConverter (который, впрочем, по умолчанию поддерживает преобразование к строке и просто вызывает ToString). Однако при использовании ресурсов никакой конвертации не производится. Ваш код приводит к вызову:
object res = new LocalizedString("foo"); fooTextBlock.Text = res;
С очевидными последствиями.
Могу предложить несколько путей:
Вместо странных костылей с ресурсами можно воспользоваться расширениями разметки MarkupExtension. Метод ProvideValue может возвращать произвольный тип и даже учитывать, какому свойству какого объекта значение сейчас присваивается. Выглядеть это в XAML будет кратко и естественно:
Продолжать городить костыли, но заставить XAML вызвать конвертеры:
Вообще-то в WPF встроены средства для локализации, но кому до них дело...
P. S. Код не тестировал, мог наврать.

Комментариев нет:

Отправить комментарий