Не знал как коротко описать суть проблемы.
Вот код xaml
Вот код c# класса LocalizedString
public class LocalizedString : IComparable, ICloneable, IEnumerable
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
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 будет кратко и естественно:
P. S. Код не тестировал, мог наврать.
Комментариев нет:
Отправить комментарий