thomasb
thomasb

Reputation: 6037

MVVM : RaisePropertyChange on another item in the same list

I am using MVVM Light in a (pretty simple) WPF project.

I have a list of versions, and for each of them there is a button "activate" and "archive". Only one version can be active.
When clicking on "activate", the software must archive the currently active version, and activate the selected one.
How would you modelize this ? I'm currently using a pretty ugly solution : the selected version re-instantiates the "active version" and archives it, so obviously the previously-active version isn't "refreshed".

The main window contains a list of versions, displayed in a ListBox (see this question).

public class MainWindowViewModel : ViewModelBase
{
    public MainWindowViewModel()
    {
        this.InstalledVersions = InstalledVersionViewModel.GetInstalledVersions();
    }

    public ObservableCollection<InstalledVersionViewModel> InstalledVersions { get; set; }
}

The InstalledVersionViewModel is (simplified) like this :

public class InstalledVersionViewModel : ViewModelBase
{
    public InstalledVersionViewModel()
    {
        this.HandleActivateVersionCommand = new RelayCommand<RoutedEventArgs>(e => { this.ActivateVersion(); });
        this.HandleArchiveVersionCommand = new RelayCommand<RoutedEventArgs>(e => { this.ArchiveVersion(); });
    }

    public string FolderPath { get; set; }

    public RelayCommand<RoutedEventArgs> HandleActivateVersionCommand { get; private set; }

    public RelayCommand<RoutedEventArgs> HandleArchiveVersionCommand { get; private set; }

    public string VersionNumber { get; set; }

    public static InstalledVersionViewModel GetCurrentVersion()
    {
        return GetVersionInfos(baseInstallPath); // returns the currently-active version
    }

    public static ObservableCollection<InstalledVersionViewModel> GetInstalledVersions()
    {
        var list = new ObservableCollection<InstalledVersionViewModel>();
        // snip : fill the list from detected versions
        return list;
    }

    private void ActivateVersion()
    {
        // snip
        GetCurrentVersion().Archive();
        // snip
    }

    private void ArchiveVersion()
    {
        // snip
    }
}

The problem is in the ActivateVersion() method : I'm getting a new version instance to archive it, so obviously the version instance in the list is never aware of this change. But I don't know how to change the behavior to archive the version in the list instead. I'm pretty sure there should be either some kind of messaging system, a wrapper or an overarching structure, but I can't quite put my finger on it.

Thanks !

Upvotes: 1

Views: 79

Answers (1)

Kevin Gosse
Kevin Gosse

Reputation: 39007

To me, it should be handled in the MainViewModel. For instance, add a property IsActive to your InstalledVersionViewModel, and subscribe to the PropertyChanged event from your MainViewModel. When the event is raised, browse your InstalledVersions list to find the previously active item, and call the Archive method on it.


To subscribe to the event, simply browse your list after creating it:

public MainWindowViewModel()
{
    this.InstalledVersions = InstalledVersionViewModel.GetInstalledVersions();

    foreach (var version in this.InstalledVersions)
    {
        version.PropertyChanged += this.VersionPropertyChanged;
    }
}

Then, in the event, check which property has been changed:

private void VersionPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "IsActive")
    {
        var changedVersion = (Version)sender;

        // Checks that the version has been activated
        if (changedVersion.IsActive)
        {
            // Finds the previously active version and archive it
            foreach (var version in this.InstalledVersions)
            {
                if (version.IsActive && version != changedVersion)
                {
                    version.Archive();
                }
            }
        }
    }
}

Upvotes: 1

Related Questions