绑定到使用更改属性的属性
我试图在WPF中实现正确的MVVM体系结构。 我有一个玩,在“模型”部分有一个布尔属性,说如果我们现在“玩”。绑定到使用更改属性的属性
public bool IsPlaying
{
get
{
return isPlaying;
}
set
{
isPlaying = value;
OnPropertyChanged("IsPlaying");
}
}
(请注意,我实现了 “INotifyPropertyChanged的” 接口)在我的ViewModel
,我有一个名为 “ToggleButtonIcon” 一个ImageSource的属性:
public ImageSource ToggleButtonIcon
{
get
{
if (Model.IsPlaying)
return pauseIcon;
else
return playIcon;
}
}
其中我绑定到“切换播放“按钮在视图中:
<cc:IconButton x:Name="TogglePlayButton"
Style="{StaticResource playButton}"
ImageSource="{Binding Path=ToggleButtonIcon,
UpdateSourceTrigger=PropertyChanged}"
Command="{Binding Path=TogglePlayCommand}"/>
(这是一个自定义控件,但它的工作,我che cked) 当然,我希望按钮根据是否正在播放(暂停)以及是否正在播放(播放)来更改图像图标。
问题是ToggleButtonIcon
不通知它何时更改,我无法在ViewModel部分实现INotifyValueChanged
,因为a。我明白那不是你怎么做的,b。我不知道它何时发生变化,因为它取决于Model的IsPlaying
属性。
我曾考虑将ToggleButtonIcon
属性放在模型部分,但这不是“业务逻辑”,所以我认为这不是正确的做法。
我也想过用转换器和绑定IconButton
直接“IsPlaying模块”,这可能会工作,但我读到这里:How can WPF Converters be used in an MVVM pattern?,你不应该在使用转换器都在MVVM,因为你可以做你想做的任何皈依在“ViewModel”部分。
在MVVM体系结构中完成此操作的最佳方法是什么?
MVVM的模型应该只包含类实体,这些实体有时可以有INotiftPropertyChanged
,但通常情况下他们不会。
你的意图是,它是传达一个状态,应该在你的视图模型上。
我建议您将IsPlaying
的状态置于View Model(VM)并绑定到该模型。然后在TogglePlayCommand
的命令中,它将在VM上设置该属性。
这样一来,两个项目都会随着更改而更新。 如果需要,您仍然可以在模型中和虚拟机IsPlaying
的Setter
上新建原始对象,并将类实例属性设置为其值(如果需要)。我的博客文章Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding。请注意我如何使用OnPropertyChanged
推送其他操作的更改消息,这些操作都可以为您寻求的灵活性以及视图模型保持状态而不是模型。
所以你建议在模型和视图模型中放置IsPlaying? 因此,“ViewModel.IsPlaying”将从“Model.IsPlaying”中获取/设置其值? –
我宁愿在ViewModel中保留任何视图操作,但它不清楚OP为什么在模型上使用它。 – OmegaMan
对于我来说,IsPlaying
应该在ViewModel中,并且实现更改通知,因为它代表了应用程序的排序状态。
为了解决这个问题,我会建议服用ToggleButtonIcon
出视图模型,并(通过其Style
)创建于IconButton
控制DataTrigger
,结合到IsPlaying
属性(在视图模型),并改变基于ImageSource
财产在那。
你应该把布尔的类,它实现接口INotifyPropertyChange: 下面的例子:
public class Game : INotifyPropertyChanged
{
private bool _isPlaying;
public string IsPlaying
{
get { return _isPlaying; }
set {
_isPlaying = value;
this.NotifyPropertyChangedBool();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChangedBool()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs("IsPlaying"));
}
}
这就是我所做的! (在“模型”杠杆),但我需要绑定一个图像,而不是布尔值。 –
你从哪里得到的想法:“这不是你怎么办呢?” ViewModels通常实现INotifyPropertyChanged。我会说这对于模型来说实际上并不常见,但你显然是这么做的。如果你这样做,那么你将不得不在视图模型中订阅模型的PropertyChanged事件,并引发相应的更改相关属性。另一种方法是绑定到模型对象,并使用DataTrigger根据IsPlaying的状态更改图像源。 –
“你从哪里得到这个主意......” - 我在YouTube上看到过一个例子。 “你将不得不订阅模型的PropertyChanged事件......” - 我该怎么做? “...并使用DataTrigger根据IsPlaying的状态更改图像源” - 这是什么意思,我该怎么做? –