如何绑定WPF GUI值以反映基础值是否为某个枚举值

时间:2013-04-09 09:37:05

标签: wpf user-interface binding enums viewmodel

我有一个WPF应用程序,可以提醒用户泵中即将发生的错误。有三种错误,我在PumpErrorModel中定义为枚举。此pumpErrorModel还知道哪种类型的错误最有可能。这是我的PumpErrorViewModel暴露给GUI,它有一个标签绑定到这个最可能的错误的值,转换为字符串。到目前为止,非常好。

// from MainWindow.xaml
<Label ... Content="{Binding LikelyError, Converter={StaticResource PumpErrorTypeToString}}" />

// from PumpErrorViewModel.cs
private PumpErrorModel.PumpErrorType likelyError;
public PumpErrorModel.PumpErrorType LikelyError {
    get { return likelyError; }
    private set { likelyError = value; RaisePropertyChanged("LikelyError"); } }

在我的GUI中,我还描述了每种类型的泵误差,即每个值的枚举值。我想将每个标签的背景绑定到最可能的错误类型的值,这样当最可能的错误类型是“Explosions”时,描述爆炸的标签有红色背景,而其他标签有白色背景。

// from MainWindow.xaml. I would like to bind the background of these
<Label Content="Likely Error: Explosions" />
<Label Content="Likely Error: More Explosions!" />
<Label Content="Likely Error: Rabbits!!!" />

我可以在viewmodel中为每种类型的错误创建一个布尔属性,指示可能的错误是否属于特定类型。然后,我可以将每个标签背景绑定到相应的属性。但是对我来说似乎有些混乱,因为我必须在原始可能错误属性的setter中对每个额外的函数调用RaisePropertyChanged。

// proposed code in PumpErrorViewModel.cs
public bool IsRabbits { get { return LikelyError == PumpErrorModel.PumpErrorType.Rabbits; } };

// amended LikelyError setter
public PumpErrorModel.PumpErrorType LikelyError {
   get ...
   private set { likelyError = value;
                 RaisePropertyChanged("LikelyError");
                 RaisePropertyChanged("IsRabbits"); } }

// proposed code in MainWindow.xaml
<Label Content="Likely Error: Rabbits!!!" BackGround="{Binding IsRabbits, Converter){StaticResource BoolToColor}}" />

如果我这样做,那么我在LikelyError和IsRabbits之间有一个耦合,每当我添加新的错误类型和布尔属性时我都会忘记。有没有更好的方法来实现我的目标?

1 个答案:

答案 0 :(得分:1)

在主视图模型上使用子集合似乎是一种很好的情况。该子集合中的每个视图模型将表示单个泵错误类型。然后,您的视图将绑定到该集合以列出所有潜在的泵错误并突出显示可能的错误。以下是我们的讨论起点:

public class MainViewModel : ViewModel
{
    private readonly ICollection<PumpErrorTypeViewModel> pumpErrorTypes;

    public MainViewModel()
    {
        this.pumpErrorTypes = Enum.GetValues(typeof(PumpErrorType))
            .Cast<PumpErrorType>()
            .Select(x => new PumpErrorTypeViewModel(x))
            .ToList();
    }

    pubilc ICollection<PumpErrorTypeViewModel> PumpErrorTypes
    {
        get { return this.pumpErrorTypes; }
    }


public class PumpErrorTypeViewModel : ViewModel
{
    private readonly PumpErrorType type;

    public PumpErrorTypeViewModel(PumpErrorType type)
    {
        this.type = type;
    }

    public PumpErrorType Type
    {
        get { return this.type; }
    }

    public string Display
    {
        // do whatever formatting you like here
        get { return string.Format("Likely Error: {0}", this.type); }
    }
}

<ItemsControl ItemsSource="{Binding PumpErrorTypes}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Label Content="{Binding Display}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

现在,为了实现标签背景的着色,我们可以通过多种方式实现这一目标,但最常见的两种方法是:

  1. MainViewModel可能拥有LikelyError属性。 PumpErrorTypeViewModel可以在其构造函数中使用MainViewModel并公开Background属性。它可以收听LikelyError中的更改并相应地使其Background无效。这非常适合反应式实现(请参阅ReactiveUI)。
  2. PumpErrorViewModel可能会公开IsLikely属性,该属性在设置时会使其Background属性无效。每当MainViewModel更改时,pumpErrorTypes都可以遍历所有LikelyError并更新孩子的IsLikely属性。
  3. 无论哪种方式,视图都有一个简单的变化:

    <Label Content="{Binding Display}" Background="{Binding Background}"/>