How can I make one model change view on another model?

I need a simple example of how to make one viewer update the property on another view model.

Here is the situation. I have a view and a viewmodel responsible for displaying a list of albums. I got another view and viewmodel responsible for adding new albums (a couple of text fields and buttons) now that a new album is being added, how can I tell the collection in a different view that the new album has been added to it? I read about frameworks that can do this for me, but Im trying to find out, so I will not use the framework for creatures ..

+3
source share
4 answers

There are several ways:

1) AlbumsVM CreateAlbumVM (, ). AlbumsVM, , CreateAlbumVM
2) CreateAlbumVM AlbumsVM. AlbumsVM.
3) AlbumsVM ObservableCollection -. CreateAlbumVM ObservableCollection, AlbumsVM
4) viewModels, AlbumWasAdded.

+1

, , , , mvvm

cource, , -! , :

public class CustomerRepository
{
    ...

    /// <summary>Raised when a customer is placed into the repository.</summary>
    public event EventHandler<CustomerAddedEventArgs> CustomerAdded;

    /// <summary>
    /// Places the specified customer into the repository.
    /// If the customer is already in the repository, an
    /// exception is not thrown.
    /// </summary>
    public void AddCustomer(Customer customer)
    {
        if (customer == null) throw new ArgumentNullException("customer");
        if (_customers.Contains(customer)) return;

        _customers.Add(customer);

        if (CustomerAdded != null)
            CustomerAdded(this, new CustomerAddedEventArgs(customer));
    }

    ...
}

, , , . (yuk!) MainViewModel. ShellViewModel. :

public class MainWindowViewModel : WorkspaceViewModel
{

    readonly CustomerRepository _customerRepository;

    public MainWindowViewModel(...)
    {
        _customerRepository = new CustomerRepository(customerDataFile);
    }

    void _createNewCustomer()
    {
        var newCustomer = Customer.CreateNewCustomer();
        var workspace = new CustomerViewModel(newCustomer, _customerRepository);
        Workspaces.Add(workspace);
        _setActiveWorkspace(workspace);
    }

    ObservableCollection<WorkspaceViewModel> _workspaces;

    void _setActiveWorkspace(WorkspaceViewModel workspace)
    {
        var collectionView = CollectionViewSource.GetDefaultView(Workspaces);
        if (collectionView != null)
            collectionView.MoveCurrentTo(workspace);
    }

 }

factory (Customer.CreateNewCustomer)? , , , .

ViewModel

, INPC, . , Email , DisplayNAme . ... " Cistomer":

public class CustomerViewModel : WorkspaceViewModel, IDataErrorInfo
{

    public CustomerViewModel(Customer customer, CustomerRepository customerRepository)
    {
        if (customer == null) throw new ArgumentNullException("customer");
        if (customerRepository == null) throw new ArgumentNullException("customerRepository");

        _customer = customer;
        _customerRepository = customerRepository;
     }

    readonly Customer _customer;

    public string Email
    {
        get { return _customer.Email; }
        set
        {
            if (value == _customer.Email) return;

            _customer.Email = value;
            base.OnPropertyChanged("Email");
        }
    }

    public override string DisplayName
    {
        get {
            if (IsNewCustomer)
            {
                return Strings.CustomerViewModel_DisplayName;
            }
            ...

            return String.Format("{0}, {1}", _customer.LastName, _customer.FirstName);
        }
    }


    #region Save Command

    /// <summary>
    /// Returns a command that saves the customer.
    /// </summary>
    public ICommand SaveCommand
    {
        get
        {
            return _saveCommand ??
                   (_saveCommand = new RelayCommand(param => _save(), param => _canSave));
        }
    }
    RelayCommand _saveCommand;

    /// <summary>
    /// Returns true if the customer is valid and can be saved.
    /// </summary>
    bool _canSave
    {
        get { return String.IsNullOrEmpty(_validateCustomerType()) && _customer.IsValid; }
    }

    /// <summary>
    /// Saves the customer to the repository.  This method is invoked by the SaveCommand.
    /// </summary>
    void _save()
    {
        if (!_customer.IsValid)
            throw new InvalidOperationException(Strings.CustomerViewModel_Exception_CannotSave);

        if (IsNewCustomer)
            _customerRepository.AddCustomer(_customer);
        base.OnPropertyChanged("DisplayName");
    }

}

ViewModel ViewModel

, , . , , . , ObservableCollection, .

public class AllCustomersViewModel : WorkspaceViewModel
{

    public AllCustomersViewModel(CustomerRepository customerRepository)
    {
        if (customerRepository == null) throw new ArgumentNullException("customerRepository");

        _customerRepository = customerRepository;

        // Subscribe for notifications of when a new customer is saved.
        _customerRepository.CustomerAdded += OnCustomerAddedToRepository;

        // Populate the AllCustomers collection with CustomerViewModels.
        _createAllCustomers();              
    }

    /// <summary>
    /// Returns a collection of all the CustomerViewModel objects.
    /// </summary>
    public ObservableCollection<CustomerViewModel> AllCustomers
    {
        get { return _allCustomers; }
    }
    private ObservableCollection<CustomerViewModel> _allCustomers;

    void _createAllCustomers()
    {
        var all = _customerRepository
            .GetCustomers()
            .Select(cust => new CustomerViewModel(cust, _customerRepository))
            .ToList();

        foreach (var cvm in all)
            cvm.PropertyChanged += OnCustomerViewModelPropertyChanged;

        _allCustomers = new ObservableCollection<CustomerViewModel>(all);
        _allCustomers.CollectionChanged += OnCollectionChanged;
    }

    void OnCustomerViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        const string IsSelected = "IsSelected";

        // Make sure that the property name we're referencing is valid.
        // This is a debugging technique, and does not execute in a Release build.
        (sender as CustomerViewModel).VerifyPropertyName(IsSelected);

        // When a customer is selected or unselected, we must let the
        // world know that the TotalSelectedSales property has changed,
        // so that it will be queried again for a new value.
        if (e.PropertyName == IsSelected)
            OnPropertyChanged("TotalSelectedSales");
    }

    readonly CustomerRepository _customerRepository;

    void OnCustomerAddedToRepository(object sender, CustomerAddedEventArgs e)
    {
        var viewModel = new CustomerViewModel(e.NewCustomer, _customerRepository);
        _allCustomers.Add(viewModel);
    }

}

!

,
Berryl

+3

.

private bool _checked;
    public bool Checked
    {
        get { return _checked; }
        set
        {
            if (value != _checked)
            {
                _checked = value;
                OnPropertyChanged("Checked");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyCHanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Then subscribe to your other view model in the ChangedEvent property and do what you need to do with it. Make sure your ViewModels implement INotifyPropertyChanged

0
source

It seems that you think that Viewmodels for each view should be isolated classes. They are not. Viewmodels repackage the underlying data so that the View can communicate with it. So create an ObservableCollection <Album> and ask both viewers to reference it. Done!

0
source

Source: https://habr.com/ru/post/1794947/


All Articles