は、いくつかの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
いくつかの例を挙げてください –