2016-08-23 4 views
0

У меня есть некоторое удовольствие с WPF, и я решил создать библиотеку с пользовательской реализацией подключенных триггеров (аналогично System.Windows.Interactivity.dll), но моя.Set DependencyProperty от отражения в преобразовании типа wpf

У меня есть класс TriggerAction, который представляет действие, вызываемое триггером. Я хочу начать с чего-то очень легкого, как установка фона кнопки, когда пользователь нажимает на нее.

Я уже написал некоторый рабочий код, например, класс EventTrigger, но у меня есть одна проблема с моим SetterTriggerAction. У меня есть два свойства зависимостей PropertyName, который представляет собой название свойства, которое должно быть установлено как Value. В методе Invoke я пытаюсь установить свойство с определенным значением.

Вот код:

internal override void Invoke(DependencyObject obj) 
{ 
     if (obj == null) 
      return; 

     if (string.IsNullOrEmpty(PropertyName)) 
      return; 

     PropertyInfo property = obj.GetType().GetProperty(PropertyName, BindingFlags.Public | BindingFlags.Instance); 

     if (property == null) 
     { 
      Debug.WriteLine("Cannot find property {0} for type {1}.", PropertyName, obj.GetType()); 
      return; 
     } 

     MethodInfo setMethod = property.GetSetMethod(); 

     if (setMethod == null) 
     { 
      Debug.WriteLine("The property {0} does not have set method.", PropertyName); 
      return; 
     } 

     try 
     { 
      setMethod.Invoke(obj, new object[] { Value }); 
     } 
     catch(Exception ex) 
     { 
      Debug.WriteLine("Exception caught {0} with message {1}", ex.GetType(), ex.Message); 
     } 
} 

Моя вторая попытка:

internal override void Invoke(DependencyObject obj) 
{ 
     if (obj == null) 
      return; 
     if (string.IsNullOrEmpty(PropertyName)) return; 
     FieldInfo property = obj.GetType().GetField(PropertyName+"Property", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); 
     if (property == null) 
     { 
      Debug.WriteLine("Cannot find dependency property {0} for type {1}.", PropertyName+"Property", obj.GetType()); 
      return; 
     } 
     try 
     { 
      DependencyProperty dp = property.GetValue(obj) as DependencyProperty; 
      if(dp == null) 
      { 
       Debug.WriteLine("Cannot get DependencyProperty {0}", PropertyName + "Property"); 
       return; 
      } 
      obj.SetValue(dp, Value); 
     } 
     catch(Exception ex) 
     { 
      Debug.WriteLine("Exception caught {0} with message {1}", ex.GetType(), ex.Message); 
     } 
    } 

В XAML я писал:

<Button HorizontalAlignment="Center" VerticalAlignment="Center" Content="Click"> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="Click"> 
       <i:SetterTriggerAction PropertyName="Background" Value="Red"/> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </Button> 

Так что, когда я нажимаю кнопку, я хочу внести свой фон красный. Однако обе версии метода Invoke страдают от проблемы с конверсией, и в моем окне вывода появляется сообщение о том, что «Red» недопустимо для свойства Background (потому что он обрабатывается как строка, а не кисть!). Есть ли способ конвертировать значение из xaml (строка «Красный») в действительное значение Brush? Я хотел бы иметь как можно более общий способ преобразования свойств.

Я считаю, что что-то похожее на то, что я хочу достичь, выполняется при анализе xaml и задаются свойства элементов управления.

Любая помощь будет оценена по достоинству.

ответ

1

Чтобы преобразовать строку в кисти можно использовать тип по умолчанию преобразователь класса в BrushConverter:

var redBrush = (Brush)new BrushConverter().ConvertFromString("Red"); 
+0

Я уже справиться с этой проблемой. Решение состоит в том, чтобы получить тип свойства и проверить, помечен ли он TypeConverterAttribute. Затем динамически создайте экземпляр конвертера и вызовите метод ConvertFrom. В сборке «PresentationCore» имеется много классов «TypeConverter» – bakala12