只有当它是需要的类型时才绑定到接口(否则使用回退)?

Binding to interface only if it is the needed type (use fallback otherwise)?

我的 ViewModel

中有以下 属性
public IEquipment Equipment
{
    get
    {
        return equipment;
    }
    set
    {
        if (equipment != value)
        {
            equipment = value;
            InvokePropertyChanged("Equipment");
        }
    }
}

这个项目本身有一个bool 属性,它绑定到我的视图中的一个Ellipse,我想将其用作指示项目:

<Ellipse Width="10" Height="10" Fill="{Binding Equipment.IsAvailable, Converter={StaticResource BoolToColorConverter}, FallbackValue=DarkGray}" Margin="1"/>

BoolToColorConverter 只是将颜色转换为绿色 (true) 或红色 (false)。在运行时 Equipment 可以是继承自 IEquipment 的两种 class 类型之一的实例。其中只有一个 IsAvailable 属性。在实践中,这很好用,我得到了红色或绿色的八倍……或者灰色,以防其他类型的设备处于活动状态。

问题是,每次 GUI 更新时,都会输出以下警告:

System.Windows.Data Warning: 40 : BindingExpression path error: 'IsAvailable' property not found on 'object'

如何避免这个问题?基本上我想绑定到这个 属性 只有当它是正确的类型时。 我可以想到两个解决方案,我不是特别喜欢:

  1. 只需将 IsAvailable 属性 添加到其他类型并将其设置为空值(BoolToColorConverter 可以处理空值和 returns 深灰色):这可能是对一个简单的 bool 没问题,但在我的实际情况下还有其他项目,这些项目非常 class 具体。
  2. 在代码隐藏中进行数据绑定:这可能有效。在启动时使用 Loaded 之类的事件在运行时根据类型手动设置绑定。但是,这对于后面的调试来说可能会很麻烦,因为项目中的所有其他 Bindings 都直接发生在 xaml 文件中。此外,Equipment 可能会在 ViewModel 的生命周期内发生变化,因此我必须以某种方式跟踪它。

Xaml 不绑定到接口,它绑定到具体类型。

如果您的类型具有不同的属性,那么您需要不同的 xaml 来绑定它们。

使用DataTemplates指定不同的xaml显示每种类型。

如果 IEquipment 的派生属性(此处以 EquipmentOtherEquipment 为例)差异很大并且不共享通用接口,则它们很可能在外貌。在这种情况下,每种类型都需要不同的 DataTemplate。这是 ContentControl 的示例,但它与自动应用的隐式数据模板(不是 x:Key,而是 DataType)在 ItemsContol 中的工作方式相同。

<ContentControl Content="{Binding Equipment}">
   <ContentControl.Resources>
      <DataTemplate DataType="{x:Type local:Equipment}">
         <Ellipse Width="10" Height="10" Fill="{Binding IsAvailable, Converter={StaticResource BoolToColorConverter}, FallbackValue=DarkGray}" Margin="1"/>
      </DataTemplate>
      <DataTemplate DataType="{x:Type local:OtherEquipment}">
         <Ellipse Width="10" Height="10" Fill="DarkGray" Margin="1"/>
      </DataTemplate>
   </ContentControl.Resources>
</ContentControl>

针对您的特定问题的解决方法可能是编写自定义的专用值转换器。

public class EquipmentAvailabilityToColorConverter : IValueConverter
{
   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   {
      if (value is Equipment equipment)
         return equipment.IsAvailable ? Brushes.Green : Brushes.Red;

      return (Brush)parameter;
   }

   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
   {
      throw new InvalidOperationException();
   }
}
<Ellipse Width="10" Height="10" Fill="{Binding Equipment, Converter={StaticResource EquipmentAvailabilityToColorConverter}, ConverterParameter={x:Static Brushes.DarkGray}}" Margin="1"/>