#wpf #wpf-controls
#wpf #элементы управления wpf
Вопрос:
Я просмотрел эту статью, но все же я не очень разбираюсь в преобразователе типов и его использовании.
http://msdn.microsoft.com/en-us/library/aa970913.aspx
Может кто-нибудь, пожалуйста, объясните, что это такое и что с ним можно сделать в WPF.
Комментарии:
1. msdn.microsoft.com/en-us/library/…
2. Хороший пост в блоге: windowsclient.net/blogs/rob_relyea/archive/2008/04/10 /…
Ответ №1:
Если у вас есть свойство, которое не имеет типа string
, но вам нужно установить его из атрибута XAML, вам необходимо преобразовать string
указанное в XAML свойство в целевой тип. Следовательно, преобразователи типов.
Ответ №2:
Например, когда вы устанавливаете свойство background в XAML, вы можете написать «Red», в коде позади вы не можете просто присвоить свойству Background строку «Red», потому что ее тип — Кисть. WPF использует преобразователь типов для преобразования из строки в кисть.
Комментарии:
1. На самом деле не имеет ничего общего с привязкой к данным.
2. как и почему я должен использовать преобразователи без привязки данных?
3. Преобразователи типов != преобразователи значений . Они совершенно разные, и первое не имеет ничего общего с привязкой данных.
Ответ №3:
WPF 4.5 Unleashed содержит подробное введение в декларативный язык XAML. Некоторые страницы можно прочитать в Google Книгах. Теперь я ссылаюсь на страницу 26.
Если мы хотим указать цвет фона Button
объекта (на самом деле Control.Background
), это то, что нам нужно сделать, пока преобразователи типов явно не добавлены (Microsoft) к используемым нами классам:
<Button>
<Button.Background>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color A="255" R="255" G="255" B="255" />
</SolidColorBrush.Color>
</Button.Background>
</SolidColorBrush>
</Button>
В этом объявлении,
<Button.Background>
<SolidColorBrush>
означает, что мы создаем экземпляр SolidColorBrush
и присваиваем его Button.Background
свойству, тип которого является Brush
абстрактным типом.
Аналогично,
<SolidColorBrush.Color>
<Color A="255" R="255" G="255" B="255" />
означает, что мы создаем экземпляр Color
с соответствующими свойствами и присваиваем ему SolidColorBrush.Color
тот тип, который есть Color
.
Первое упрощение возможно при использовании явного преобразователя, способного понять, что строковый литерал White
, предоставленный в качестве содержимого элемента Color
XML, должен быть преобразован в Color
экземпляр, полученный с Color.FromArgb(255, 255, 255, 255)
помощью . Это упрощение теперь позволяет нам писать:
<Button>
<Button.Background>
<SolidColorBrush>
<SolidColorBrush.Color>
White
</SolidColorBrush.Color>
</Button.Background>
</SolidColorBrush>
</Button>
Возможность использования такого преобразователя была явно добавлена в объявление Color
структуры путем указания атрибута преобразователя типов:
[TypeConverter(typeof(ColorConverter))]
public struct Color : IFormattable, IEquatable<Color>
Преобразователем является ColorConverter.
Давайте продвинемся на шаг дальше и добавим преобразователь типов Brush
, тип элемента управления.Предыстория.
[TypeConverter(typeof(BrushConverter))]
public abstract class Brush : Animatable, IFormattable, DUCE.IResource
Этот преобразователь заменит допустимое содержимое строкового литерала SolidColorBrush
экземпляром и теперь позволяет:
<Button>
<Button.Background>
White
</SolidColorBrush>
</Button>
Это механизм, лежащий в основе упрощений, допускаемых XAML при интерпретации содержимого XML. Последнее упрощение, допускаемое XAML: мы можем использовать синтаксис атрибута XAML, а не синтаксис элемента:
<Button Background="White" />
Вау! мы начали с 9 строк кода, а закончили только одной!
Последнее слово о том, как интерпретируется содержимое строкового литерала XML-элемента (все из той же книги):
Правила обработки XAML для дочерних элементов объекта
Теперь вы увидели три типа дочерних элементов для элементов объекта. Чтобы избежать двусмысленности, любой допустимый анализатор или компилятор XAML следует этим правилам при обнаружении и интерпретации дочерних элементов:
Если тип реализует IList, вызовите IList .Добавьте для каждого дочернего элемента.
В противном случае, если тип реализует IDictionary, вызовите IDictionary .Добавьте для каждого дочернего элемента, используя значение атрибута x:Key для ключа и элемент для значения. (Хотя XAML2009 проверяет IDictionary перед IList и поддерживает другие интерфейсы сбора, как описано ранее.)
В противном случае, если родительский элемент поддерживает свойство содержимого (указывается System.Windows.Разметка.ContentPropertyAttribute) и тип дочернего элемента совместим с этим свойством, рассматривайте дочерний элемент как его значение.
В противном случае, если дочерним элементом является обычный текст и существует преобразователь типов для преобразования дочернего элемента в родительский тип (и для родительского элемента не заданы свойства), обработайте дочерний элемент как входные данные для преобразователя типов и используйте выходные данные в качестве экземпляра родительского объекта.
В противном случае обработайте его как неизвестное содержимое и, возможно, вызовите ошибку.
Чтобы ответить на ваш вопрос о преимуществе конвертера по-другому: это преимущество вытекает из правила 4 выше.