简体   繁体   中英

How to update UI change when property changed in MVVM

I'm trying to accomplish a correct MVVM architecture in WPF.

I have a player, in the "Model" section there is a Boolean property that says if we are "playing" right now.

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

(Notice I implemented the "INotifyPropertyChanged" interface, so the OnPropertyChanged function reports the change)

in my ViewModel, I have a ImageSource property called "ToggleButtonIcon":

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

Which I bind to a "TogglePlayButton" in the view:

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

(It's a custom control, but it's working, I checked) Of course I want the button to change its image icon according to if it is playing (pause) and if it is not playing (play).

Problem is the ToggleButtonIcon does not notify when it changes, and I can't implement the INotifyValueChanged in the ViewModel section because a. I understood that's not a part of the MVVM architexture, and b. I don't know when it changes since it depends on the IsPlaying property of Model.

I thought about putting the ToggleButtonIcon property on the Model section, but that's not "Business Logic" so I don't think that's the right way.

I also thought about using a converter and bind the IconButton directly to "IsPlaying", which would probably work, but I read here: How can WPF Converters be used in an MVVM pattern? that you should not use converters at all in MVVM because you can do any convertion you want in the "ViewModel" Section.

What's the best way to accomplish this in MVVM architecture?

To me, IsPlaying should be in the ViewModel, with change notification implemented, as it represents an application state of sorts.

To solve the issue I would recommend taking the ToggleButtonIcon out of the ViewModel, and creating a DataTrigger on the IconButton control (via its Style ), that binds to the IsPlaying property (on the ViewModel) and alters the ImageSource property based on that.

The model of MVVM should only hold class entities and those entities can on occasion have an INotiftPropertyChanged , but generally they do not.

What your intent though is that it is to convey a status and that should be on your viewmodel.

I would recommend that you have the status of IsPlaying be on the View Model (VM) and bind to that. Then in the command of TogglePlayCommand , it will set that property on the VM.

That way both items update propertly on a change to either. You can still new up your original object in the model and on the Setter of the VM's IsPlaying set the class instance property to its value if needed .


Take a look at my blog post Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding . Take note on how I use OnPropertyChanged to push change messages on other operations which can all for the flexibility you seek as well as having the viewmodel hold statuses and not the models.

You should put bool on class which implements interface INotifyPropertyChange: Here an example:

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"));
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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