来自枚举的MVVM绑定



我正在进行我的第一个WPF/MVVM项目,我很难把我的大脑集中在一些事情上。这个项目将是VB中已经制作的东西的独立应用程序,因此所有的逻辑和业务规则都已经存在。

我遇到的问题是试图实现绑定。我的应用程序上有几个按钮,它们的所有属性(IsEnabled、Text、image)都依赖于枚举。枚举基于状态,并且存在于模型中。

在VB应用程序中,我有一个巨大的switch语句来刷新按钮的属性,它在状态可能发生变化的每个地方都被调用。因此,对于这个版本,我的ViewModel中的每个按钮都有一个基于状态的bool和字符串,但无法强制它在每次状态更改时进行更新(这是非常频繁的)。

我读过一些关于INotifyPropertyChanged的内容,但需要在ViewModel中启动更改的属性在我的Model中。我是不是搞错了?

我会在您的按钮样式中使用DataTrigger。无论何时更新绑定值,都会重新评估DataTrigger,并在必要时设置新值

<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<DataTrigger Binding="{Binding MyEnumProperty}" 
Value="{x:Static local:MyEnum.Value1}">
<Setter Property="IsEnabled" Value="False" />
<Setter Property="Content" Value="Value 1" />
</DataTrigger>
<DataTrigger Binding="{Binding MyEnumProperty}" 
Value="{x:Static local:MyEnum.Value2}">
<Setter Property="IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>

您可以对Image样式执行相同的操作-根据Status枚举的当前值在DataTrigger中设置Image.Source属性。

请记住,MyEnumProperty在更改时需要引发PropertyChange通知,以便UI知道该值已更改,并更新依赖该值的任何绑定。

您需要将每个ButtonIsEnabledTextImage属性绑定到视图模型的Status属性。然后,您将需要提供IValueConverter的3个实现,它基本上将Status枚举值转换为您要查找的适当布尔、字符串或图像。对于每个Button控件,提供一个附加参数,转换器可以使用该参数与视图模型的Status属性进行比较。

类似这样的东西:

<myView.Resources>
<local:statToBoolConverter x:Key="statToBoolConv" />
<local:statToTextConverter x:Key="statToTextConv" />
<local:statToImgConverter x:Key="statToImgConv" />
</myView.Resources>
// ..... further down in code ....
<Button x:Key="aButton" 
IsEnabled="{Binding Path=Status, Converter={StaticResource statToBoolConv}, 
ConverterParamter=caseA}"
Text="{Binding Path=Status, Converter={StaticResource statToTextConv}, 
ConverterParamter=caseA}"
Image="{Binding Path=Status, Converter={StaticResource statToImgConv},
ConverterParamter=caseA}"/>
<Button x:Key="aButton" 
IsEnabled="{Binding Path=Status, Converter={StaticResource statToBoolConv}, 
ConverterParamter=caseB}"
Text="{Binding Path=Status, Converter={StaticResource statToTextConv}, 
ConverterParamter=caseB}"
Image="{Binding Path=Status, Converter={StaticResource statToImgConv},
ConverterParamter=caseB}"/>

我不打算包括实现IValueConverter的细节,因为它非常简单,但您可以在这里获得更多信息(包括示例):

http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

还有一点需要注意:INotifyPropertyChanged将触发所有按钮的绑定更新,所以只调用一个NotifyPropertyChanged("MyStatus")就可以了。

我曾试图在WPF中处理到enum的绑定,但我并不喜欢它。

您可以通过将属性映射到模型中的相应属性来解决此问题,在get方法中,您可以实现对枚举状态的依赖关系。

例如:

<Button  Height="41" HorizontalAlignment="Center" Style="{StaticResource ButtonStyle}"
Margin="407,77,289,0" Name="buttonSearch" VerticalAlignment="Top" Width="137" Click="search_click" 
IsEnabled="{Binding IsSearchButtonEnabled}" ...

假设你有这个枚举:

public enum States
{
StateOne,
StateTwo,
StateThree
}

在视图模型中,您可以这样做:

public bool IsSearchButtonEnabled
{
get
{
return ((Model.actualState) == States.StateTwo);
}
}

若要自动更新,ViewModel必须实现INotifyPropertyChanged。我使用ViewModels总是子类化的通用实现来简化事情。它看起来像这样,并且应该在每次调用InvokePropertyChanged(字符串propertyName)时处理视图的更新。ViewModel需要知道它应该更新视图,并知道何时调用此方法。您可以在Model中使用相同的技术,并在Model中放置一个事件处理程序,通知订阅虚拟机状态枚举的setter中的更改。

public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public static event PropertyChangedEventHandler PropertyChangedStatic;
public void InvokePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public static void InvokePropertyChangedStatic(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChangedStatic;
if (handler != null) handler(null, new PropertyChangedEventArgs(propertyName));
}
} 

在MVVM中,您不应该直接从ViewModel引用视图中的任何内容。

最好的解决方案是使用命令,如MVVM Light RelayCommand,它具有基于枚举属性值的CanExecute操作。然后将按钮的命令属性bind绑定到ViewModel中相应的命令属性。这将自动设置按钮的启用状态。

然后在枚举属性的set方法中,为每个命令调用CanExecuteChanged事件。

相关内容

  • 没有找到相关文章

最新更新