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

时间:2017-11-25 22:19:55

标签: c# wpf 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属性,但这不是“业务逻辑”所以我认为这不是正确的方法。

我还考虑过使用转换器并将IconButton直接绑定到“IsPlaying”,这可能会有效,但我在这里读到:How can WPF Converters be used in an MVVM pattern?你不应该在MVVM中使用转换器,因为你可以在“ViewModel”部分进行任何你想要的转换。

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

2 个答案:

答案 0 :(得分:2)

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

要解决此问题,我建议您将ToggleButtonIcon从ViewModel中取出,并在DataTrigger控件上创建IconButton(通过其Style)绑定到IsPlaying属性(在ViewModel上)并根据该属性更改ImageSource属性。

答案 1 :(得分:0)

你应该把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"));
        }
    }