繁体   English   中英

如何在MVVM中更改属性时更新UI更改

[英]How to update UI change when property changed in MVVM

我正在尝试在WPF中完成正确的MVVM架构。

我有一个玩家,在“模型”部分有一个布尔属性,说明我们现在正在“玩”。

public bool IsPlaying
    {
        get
        {
            return isPlaying;
        }
        set
        {
            isPlaying = value;
            OnPropertyChanged("IsPlaying");
        }
    }

(注意我实现了“INotifyPropertyChanged”接口,因此OnPropertyChanged函数报告了更改)

在我的ViewModel中,我有一个名为“ToggleButtonIcon”的ImageSource属性:

public ImageSource ToggleButtonIcon
    {
        get
        {
            if (Model.IsPlaying)
                return pauseIcon;
            else
                return playIcon;
        }
    }

我在视图中绑定到“TogglePlayButton”:

<cc:IconButton x:Name="TogglePlayButton" 
               Style="{StaticResource playButton}" 
               ImageSource="{Binding Path=ToggleButtonIcon,
               UpdateSourceTrigger=PropertyChanged}"  
               Command="{Binding Path=TogglePlayCommand}"/>

(这是一个自定义控件,但它正在工作,我检查了)当然我希望按钮根据它是否正在播放(暂停)以及是否正在播放(播放)来更改其图像图标。

问题是ToggleButtonIcon在更改时没有通知,我无法在ViewModel部分实现INotifyValueChanged ,因为a。 我明白这不是MVVM架构的一部分,而且b。 我不知道它何时发生变化,因为它取决于Model的IsPlaying属性。

我想过将ToggleButtonIcon属性放在Model部分,但那不是“业务逻辑”所以我认为这不是正确的方法。

我还想过使用转换器并将IconButton直接绑定到“IsPlaying”,这可能会起作用,但我在这里读到: 如何在MVVM模式中使用WPF转换器? 你不应该在MVVM中使用转换器,因为你可以在“ViewModel”部分中进行任何你想要的转换。

在MVVM架构中实现这一目标的最佳方法是什么?

对我来说, IsPlaying应该在ViewModel中,并且实现了更改通知,因为它代表了各种应用程序状态。

为了解决这个问题,我建议从ViewModel中取出ToggleButtonIcon ,并在IconButton控件上创建一个DataTrigger (通过它的Style ),它绑定到IsPlaying属性(在ViewModel上)并根据它改变ImageSource属性。

MVVM的模型应该只包含类实体,这些实体有时可以有一个INotiftPropertyChanged ,但通常它们不会。

你的意图是,它是传达一个状态,应该在你的viewmodel上。

我建议你将IsPlaying的状态放在View Model(VM)上并绑定到它。 然后在TogglePlayCommand的命令中,它将在VM上设置该属性。

这样两个项目都会在更改时更新属性。 您仍然可以在模型中创建原始对象,并在VM的IsPlayingSetter上将类实例属性设置为其值(如果需要)


看看我的博客文章Xaml:ViewModel主页实例化和加载策略更容易绑定 请注意我如何使用OnPropertyChanged在其他操作上推送更改消息,这些操作既可以实现您所寻求的灵活性,也可以使视图模型保持状态而不是模型。

你应该把bool放在实现接口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"));
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM