2015-07-07 10 views
1

У меня есть ситуация, когда я использую конвертер с несколькими значениями. Значения, переданные ему, сами преобразуются.Укажите тип цели для IValueConverter

<MenuItem> 
    <MenuItem.IsEnabled> 
     <MultiBinding Converter="{StaticResource BooleanAndConverter}"> 
      <Binding Path="Prop1" Converter="{StaticResource Converter1}" /> 
      <Binding Path="Prop2" Converter="{StaticResource Converter1}" /> 
     </MultiBinding> 
    </MenuItem.IsEnabled> 
</MenuItem 

Конвертер1 содержит некоторую проверку ошибок, подтверждающую, что он вызывается с допустимым типом цели. Он генерирует исключение, если нет, поскольку это ошибка разработчика, и ситуация должна быть исправлена.

Проблема заключается в том, что при использовании Converter1 в этом контексте целевым типом является System.Object. Теперь BooleanAndConverter требует значений определенного типа (Boolean), поэтому как я могу получить этот тип, переданный в качестве целевого типа Converter1?

В соответствии с поручением здесь код BooleanAndConverter:

public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     foreach (object value in values) 
     { 
      if (value.GetType() != typeof(bool)) 
      { 
       throw new ArgumentException("BooleanAndConverter can only be used to convert booleans."); // developer error 
      } 
     } 

     if (targetType != typeof(bool)) 
     { 
      throw new ArgumentException("BooleanAndConverter can only convert to a boolean."); // developer error 
     } 

     foreach (object value in values) 
     { 
      if ((bool)value == false) 
      { 
       return false; 
      } 
     } 
     return true; 
    } 

Позвольте мне переформулировать вопрос, как кажется, есть некоторая путаница. Converter1 знает, какой тип он может конвертировать из и в. Он выдает исключение при вызове с неправильными типами. В этой ситуации целевой тип не задается и генерируется исключение. Как правильно определить targetType? Когда он не используется в ситуации с несколькими связями, всегда задается правильно в зависимости от того, что преобразуется.

+0

Является ли это просто коробочный логическое значение? Вы посмотрели на него в отладчике, чтобы определить базовый тип переданного объекта? –

+0

отправьте код для BooleanAndConverter, пожалуйста. –

+0

@AbinMathew Я добавил функцию преобразования к вопросу. – denver

ответ

0

Возможной альтернативой некоторым комментариям с помощью CommandParameter может быть MarkupExtension. Тогда вы могли бы написать MultiBinding как:

<MultiBinding Converter="{StaticResource BooleanAndConverter}"> 
    <Binding Path="Prop1" Converter="{conv:DebugTypeCheck, CheckType={x:Type sys:Boolean}" /> 
    <Binding Path="Prop2" Converter="{StaticResource DebugTypeCheckConverter}" CommandParameters="{x:Type sys:Boolean}" /> 
</MultiBinding> 

На StackOverflow вы можете найти несколько сообщений о MarkupExtension-преобразователи, как here.

Пример реализации для обоих способов:

public class DebugTypeCheck : MarkupExtension, IValueConverter 
{ 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return this; 
    } 

    public Type CheckType { get; set; } 

    [Conditional("DEBUG")] 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (value.GetType() != CheckType) 
     { 
      throw new ArgumentException(); // developer error 
     } 

     return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

public class DebugTypeCheckConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (value.GetType() != (Type)parameter) 
     { 
      throw new ArgumentException(); // developer error 
     } 

     return value; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
+0

Мне нравится это решение, поскольку оно по-прежнему позволяет проверять тип, чтобы избежать ошибок времени выполнения. Вы можете сделать это так, чтобы он выполнял проверку против параметра, если он предоставлен, иначе он будет проверяться на целевой тип. В итоге я немного изменил подход. Вместо этого я решил проверить, что тип, который я хотел вернуть, можно безопасно применить к типу цели. if (! targetType.IsAssignableFrom (typeof (TheTypeIWantToReturn))) {} – denver

0

Мне кажется, что код в конвертере должен отличать объект от любого типа, который он ожидает.

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    var desired = value as desiredType; 
    if (desired != null) 
     //do stuff with 'desired' as a parameter 
    else 
     // error 
} 

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

+1

Это не тип значения, который является проблемой. значение явно передано в. Это тип targetType, который не указан. – denver