2015-02-13 5 views
3

Недавно я прочитал около IValueConverter, который также наследует от MarkupExtension. Это было что-то вроде:IValueConverter с MarkupExtension

internal class BoolToVisibilityConverter : MarkupExtension, IValueConverter 
{ 
    private static BoolToVisibilityConverter converter; 
    public BoolToVisibilityConverter() 
    { 
    } 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is bool) 
     { 
      if ((bool)value) 
      { 
       return Visibility.Visible; 
      } 
     } 
     return Visibility.Collapsed; 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is Visibility) 
     { 
      Visibility visibility = (Visibility)value; 
      if (visibility == Visibility.Collapsed) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return converter ?? (converter = new BoolToVisibilityConverter()); 
    } 
} 

Использование чем выглядит следующим образом:

<Button Content="Delete" Visibility="{Binding CanDelete, UpdateSourceTrigger=PropertyChanged, Converter={local:BoolToVisibilityConverter}"/> 

Я привык использовать конвертеры из ресурсов, как:

<loc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/> 
... 
<Button Content="Delete" Visibility="{Binding CanDelete, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibilityConverter}"/> 

Мой первый вопрос сейчас: что это лучший способ? Какие преимущества у него есть, если я использую MarkupExtension-Version (кроме использования проще набрать)?

Я также видел очень похожую реализацию, которая выглядит следующим образом:

internal class BoolToVisibilityConverter : MarkupExtension, IValueConverter 
{ 
    public BoolToVisibilityConverter() 
    { 
    } 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is bool) 
     { 
      if ((bool)value) 
      { 
       return Visibility.Visible; 
      } 
     } 
     return Visibility.Collapsed; 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is Visibility) 
     { 
      Visibility visibility = (Visibility)value; 
      if (visibility == Visibility.Collapsed) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return this;   
    } 
} 

Если я правильно понимаю, то первое решение только создает один экземпляр этого преобразователя. Второй создает для каждого XAML новый экземпляр этого конвертера, правильно?

ответ

5

Единственное (небольшое) преимущество, которое расширение расширения разметки в этом случае является более сжатым синтаксисом XAML.

Вместо этого:

<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
... 
{Binding SomeBooleanProperty, Converter={StaticResource BooleanToVisibilityConverter}} 

вы можете иметь это:

{Binding SomeBooleanProperty, Converter={my:BoolToVisibilityConverter}} 

На мой взгляд, это на самом деле не стоит. Если бы вы были, что побеспокоился об экономии нажатий клавиш можно просто сократить ключ, используемый для ссылки на преобразователь:

<BooleanToVisibilityConverter x:Key="btvc" /> 
... 
{Binding SomeBooleanProperty, Converter={StaticResource my:btvc}} 

Как ProvideValue метод расширения разметки является экземпляр метод, его можно назвать только как только экземпляр класса был создан. Поскольку класс является расширением разметки и конвертером, оба варианта кода будут создавать конвертер каждый раз. Единственное отличие состоит в том, что первый вариант всегда будет вернуть тот же конвертер: он, однако, не остановит другой преобразователь от , созданный.