2011-02-26 8 views
3

1つのビューモデルを別のビューモデルのプロパティに更新する簡単な例が必要です。1つのビューモデルを別のビューモデルのプロパティに更新させるにはどうすればよいですか?

ここに状況があります。私は、アルバムのリストを表示するビューとビューモデルに責任があります。私は新しいアルバムは、私は新しいアルバムが追加されたことが、他のビューでコレクションを教えてくださいどのように追加される今、追加された新しいアルバム(テキストボックスのカップルやボタン)のための別のビューとのviewmodelの責任があるの? 私のためにこれを行うことができるフレームワークについて読んだが、学習しようとしているので、私は存在のためのフレームワークを使用しない。

答えて

1

を実装していることを確認してください:

1)AlbumsVMを(例えば第一、第二を開きます)CreateAlbumVMを認識しています。この場合、あなたは単にCreateAlbumVMAlbumsVMを認識している)
が提供する詳細を使用してAlbumsVMにアルバムを追加することができます。その後、アルバムをAlbumsVMに挿入することができます。
3)AlbumsVMがどこからObservableCollectionとしてアルバムを受けます。その後、CreateAlbumVMは、AlbumsVM
に反映される元のObservableCollectionに新しいアルバムを挿入することができます4)イベントAlbumWasAddedを提供するこれらのviewModelsの間にいくつかのメディエータがあります。ここ

+0

いくつかの例を挙げてください –

0

このようなプロパティを実装する。

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

次に、他のviewmodelをpropertyChangedEventに登録し、必要な処理を行います。 は、あなたのviewmodelsがあり、いくつかの方法INotifyPropertyChangedの

+0

入力のThx。私は、2つのビューモデルの知識を持つコントローラを作成することに決めました。 – Ols1

3

は、いくつかのJosh Smith's classic demo appから持ち上げパズルのピース、イベントはテスト容易性をサポートするために使用することができる方法を示すとMVVM

によってもたらさ緩い夫婦は、これはのビューモデルではありません

データであり、讲义1コース、しかし最も興味深いアプリケーションは、データを持っている&それがどこから来ています!そしてそれは、新しいアイテムが追加されたときのイベントを保持するための明白かつ便利な候補である:

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

} 

モデルオブジェクト

あなたはstaticファクトリコンストラクタメソッド(Customer.CreateNewCustomer)を気づきましたか?それが目的だものを明確にさせ、そして新しい顧客の作成に関する任意の複雑さをカプセル化する機会を与えてくれます。

モデルオブジェクトビューモデルラッパー

それはデータバインディングのための基礎であるので、これは、典型的には、使用するINPC通知が簡単になり、基本クラスから派生します。Emailプロパティはモデルオブジェクトのemailプロパティに直接渡されますが、DisplayNAmeは純粋にUI駆動型であることに注意してください。新しいアイテムを追加する場合には、それが適切に言う... "新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"); 
    } 

}

のviewmodels

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

} 

完全な記事をチェックしてコードをダウンロードしてください。

HTH、
Berryl

0

あなたは、各ビューについてのviewmodelsクラスを分離するべきだと思う印象を与えます。ではない。 ViewModelは、Viewがバインドできるように基になるデータを再パッケージ化します。したがって、ObservableCollectionを作成し、両方のViewModelで参照してください。完了!

関連する問題