WPFのためのMVVMデザイン パターン
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
&tag(WPF,MVVM,WPFのためのMVVMデザイン パターン);
*目次 [#ka793b28]
#contents
*参考情報 [#i940a73b]
-[[WPF のための MODEL-VIEW-VIEWMODEL (MVVM) デザイン パタ...
*概要 [#sf66f6d2]
-顧客情報を一覧表示するビューと顧客情報を新規追加するビュ...
*RelayCommandの役割 [#uc595673]
-ViewにViewModelがバインドされ、ButtonなどにViewModelのIC...
-ICommandからViewModelの内部構造に触りたい。しかしIComman...
-例えばCutomerViewModelでは次のように定義されている。
#pre{{
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand(
param => this.Save(),
param => this.CanSave
);
}
return _saveCommand;
}
}
}}
-CustomerView.xamlでは次のようにバインドされている。
#pre{{
<!-- SAVE BUTTON -->
<Button
Grid.Row="8" Grid.Column="2"
Command="{Binding Path=SaveCommand}"
Content="_Save"
HorizontalAlignment="Right"
Margin="4,2"
MinWidth="60"
/>
}}
*ViewModelの構造 [#ve640666]
-ViewModelは継承構造となっている。
**ViewModelBase [#i61fb092]
-ViewModelの階層のルート。
-INotifyPropertyChangedインターフェイスを実装。ViewModel...
-サブクラスのために、OnPropertyChanged()メソッドを公開し...
#pre{{
// In ViewModelBase.cs
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyN...
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyCh...
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] ...
{
string msg = "Invalid property name: " + property...
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
}}
-CustomewViewModelサブクラスからはつぎのように呼び出され...
#pre{{
public string Email
{
get { return _customer.Email; }
set
{
if (value == _customer.Email)
return;
_customer.Email = value;
base.OnPropertyChanged("Email");
}
}
}}
**CommandViewModel [#r790134d]
-メインウィンドウに表示される。"View all customers", "Cre...
-コマンドをセットして実行するだけの役割。
-MainWindowViewModelで次のように生成されている。
#pre{{
public ReadOnlyCollection<CommandViewModel> Comma...
{
get
{
if (_commands == null)
{
List<CommandViewModel> cmds = this.Cr...
_commands = new ReadOnlyCollection<Co...
}
return _commands;
}
}
List<CommandViewModel> CreateCommands()
{
return new List<CommandViewModel>
{
new CommandViewModel(
Strings.MainWindowViewModel_Command_V...
new RelayCommand(param => this.ShowAl...
new CommandViewModel(
Strings.MainWindowViewModel_Command_C...
new RelayCommand(param => this.Create...
};
}
}}
-MainWindowResource.xamlでDateTemplateとして定義され、Mai...
#pre{{
<DataTemplate x:Key="CommandsTemplate">
<ItemsControl IsTabStop="False" ItemsSource="{Binding...
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Margin="2,6">
<Hyperlink Command="{Binding Path=Command}">
<TextBlock Text="{Binding Path=DisplayName}...
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
}}
**WorkspaceViewModel [#i4e571b0]
-ViewModelBaseを直接継承し、「閉じる」機能を実装。
**MainWindowViewModel [#pd103d5d]
-メニューから呼び出される「閉じる」機能は、AppクラスのOnS...
#pre{{
EventHandler handler = null;
handler = delegate
{
viewModel.RequestClose -= handler;
window.Close();
};
viewModel.RequestClose += handler;
}}
-顧客一覧ビュー、顧客登録ビューの各タブにある×ボタンがお...
--ObservableCollection<WorkspaceViewModel> _workspacesで...
--タブ生成時にViewModelに、CustomerViewModel、AllCustomer...
--OnWorkspacesChanged()により、生成されたViewModelのReque...
--これにより、×が押されたときに、MainWindowViewModelのOnW...
ちなみに、タブ生成時は次のコードでタブの順番を制御してい...
#pre{{
void SetActiveWorkspace(WorkspaceViewModel worksp...
{
Debug.Assert(this.Workspaces.Contains(workspa...
ICollectionView collectionView = CollectionVi...
if (collectionView != null)
collectionView.MoveCurrentTo(workspace);
}
}}
※[[Bea Stollnitz » WPF’s CollectionViewSource:http:/...
*データモデルとリポジトリ [#pff35a78]
-全てのCustomerはCustomerRepositoryで管理される。
-CustomerViewModelでSave()が実行されるとCustomerRepositor...
*新しい顧客のデータ入力フォーム [#i138ca69]
-CustomerView.xamlが定義。
-Customerクラス・CustomerViewModelクラスの検証メソッドに...
-Customer Typeリストボックスの初期値は"(Not Specified)"。...
-CustomerViewModelでは次のようにリストボックスの選択肢と...
#pre{{
public string[] CustomerTypeOptions
{
get
{
if (_customerTypeOptions == null)
{
_customerTypeOptions = new string[]
{
"(Not Specified)",
"Person",
"Company"
};
}
return _customerTypeOptions;
}
}
public string CustomerType
{
get { return _customerType; }
set
{
if (value == _customerType ||
String.IsNullOrEmpty(value))
return;
_customerType = value;
if (_customerType == "Company")
{
_customer.IsCompany = true;
}
else if (_customerType == "Person")
{
_customer.IsCompany = false;
}
base.OnPropertyChanged("CustomerType");
base.OnPropertyChanged("LastName");
}
}
}}
-保存時はCustomerクラスのIsValid()により検証している。
*顧客一覧 [#q08767ad]
-AllCustomersView.xamlで定義。
-CustomerViewModelの一覧が、AllCustomersとして公開されて...
#pre{{
public ObservableCollection<CustomerViewModel> All...
}}
-CustomerRepositoryを監視し、Customerが追加されたタイミン...
#pre{{
void OnCustomerAddedToRepository(object sender, Cu...
{
var viewModel = new CustomerViewModel(e.NewCu...
this.AllCustomers.Add(viewModel);
}
}}
-顧客が選択されたり選択解除されたりしたときのために、Cust...
-CustomerViewModelのIsSelectedが変更された結果OnCustomerV...
#pre{{
void OnCustomerAddedToRepository(object sender, C...
{
var viewModel = new CustomerViewModel(e.NewCu...
this.AllCustomers.Add(viewModel);
}
}}
*ポイント [#o666aeff]
終了行:
&tag(WPF,MVVM,WPFのためのMVVMデザイン パターン);
*目次 [#ka793b28]
#contents
*参考情報 [#i940a73b]
-[[WPF のための MODEL-VIEW-VIEWMODEL (MVVM) デザイン パタ...
*概要 [#sf66f6d2]
-顧客情報を一覧表示するビューと顧客情報を新規追加するビュ...
*RelayCommandの役割 [#uc595673]
-ViewにViewModelがバインドされ、ButtonなどにViewModelのIC...
-ICommandからViewModelの内部構造に触りたい。しかしIComman...
-例えばCutomerViewModelでは次のように定義されている。
#pre{{
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand(
param => this.Save(),
param => this.CanSave
);
}
return _saveCommand;
}
}
}}
-CustomerView.xamlでは次のようにバインドされている。
#pre{{
<!-- SAVE BUTTON -->
<Button
Grid.Row="8" Grid.Column="2"
Command="{Binding Path=SaveCommand}"
Content="_Save"
HorizontalAlignment="Right"
Margin="4,2"
MinWidth="60"
/>
}}
*ViewModelの構造 [#ve640666]
-ViewModelは継承構造となっている。
**ViewModelBase [#i61fb092]
-ViewModelの階層のルート。
-INotifyPropertyChangedインターフェイスを実装。ViewModel...
-サブクラスのために、OnPropertyChanged()メソッドを公開し...
#pre{{
// In ViewModelBase.cs
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyN...
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyCh...
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] ...
{
string msg = "Invalid property name: " + property...
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
}}
-CustomewViewModelサブクラスからはつぎのように呼び出され...
#pre{{
public string Email
{
get { return _customer.Email; }
set
{
if (value == _customer.Email)
return;
_customer.Email = value;
base.OnPropertyChanged("Email");
}
}
}}
**CommandViewModel [#r790134d]
-メインウィンドウに表示される。"View all customers", "Cre...
-コマンドをセットして実行するだけの役割。
-MainWindowViewModelで次のように生成されている。
#pre{{
public ReadOnlyCollection<CommandViewModel> Comma...
{
get
{
if (_commands == null)
{
List<CommandViewModel> cmds = this.Cr...
_commands = new ReadOnlyCollection<Co...
}
return _commands;
}
}
List<CommandViewModel> CreateCommands()
{
return new List<CommandViewModel>
{
new CommandViewModel(
Strings.MainWindowViewModel_Command_V...
new RelayCommand(param => this.ShowAl...
new CommandViewModel(
Strings.MainWindowViewModel_Command_C...
new RelayCommand(param => this.Create...
};
}
}}
-MainWindowResource.xamlでDateTemplateとして定義され、Mai...
#pre{{
<DataTemplate x:Key="CommandsTemplate">
<ItemsControl IsTabStop="False" ItemsSource="{Binding...
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Margin="2,6">
<Hyperlink Command="{Binding Path=Command}">
<TextBlock Text="{Binding Path=DisplayName}...
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
}}
**WorkspaceViewModel [#i4e571b0]
-ViewModelBaseを直接継承し、「閉じる」機能を実装。
**MainWindowViewModel [#pd103d5d]
-メニューから呼び出される「閉じる」機能は、AppクラスのOnS...
#pre{{
EventHandler handler = null;
handler = delegate
{
viewModel.RequestClose -= handler;
window.Close();
};
viewModel.RequestClose += handler;
}}
-顧客一覧ビュー、顧客登録ビューの各タブにある×ボタンがお...
--ObservableCollection<WorkspaceViewModel> _workspacesで...
--タブ生成時にViewModelに、CustomerViewModel、AllCustomer...
--OnWorkspacesChanged()により、生成されたViewModelのReque...
--これにより、×が押されたときに、MainWindowViewModelのOnW...
ちなみに、タブ生成時は次のコードでタブの順番を制御してい...
#pre{{
void SetActiveWorkspace(WorkspaceViewModel worksp...
{
Debug.Assert(this.Workspaces.Contains(workspa...
ICollectionView collectionView = CollectionVi...
if (collectionView != null)
collectionView.MoveCurrentTo(workspace);
}
}}
※[[Bea Stollnitz » WPF’s CollectionViewSource:http:/...
*データモデルとリポジトリ [#pff35a78]
-全てのCustomerはCustomerRepositoryで管理される。
-CustomerViewModelでSave()が実行されるとCustomerRepositor...
*新しい顧客のデータ入力フォーム [#i138ca69]
-CustomerView.xamlが定義。
-Customerクラス・CustomerViewModelクラスの検証メソッドに...
-Customer Typeリストボックスの初期値は"(Not Specified)"。...
-CustomerViewModelでは次のようにリストボックスの選択肢と...
#pre{{
public string[] CustomerTypeOptions
{
get
{
if (_customerTypeOptions == null)
{
_customerTypeOptions = new string[]
{
"(Not Specified)",
"Person",
"Company"
};
}
return _customerTypeOptions;
}
}
public string CustomerType
{
get { return _customerType; }
set
{
if (value == _customerType ||
String.IsNullOrEmpty(value))
return;
_customerType = value;
if (_customerType == "Company")
{
_customer.IsCompany = true;
}
else if (_customerType == "Person")
{
_customer.IsCompany = false;
}
base.OnPropertyChanged("CustomerType");
base.OnPropertyChanged("LastName");
}
}
}}
-保存時はCustomerクラスのIsValid()により検証している。
*顧客一覧 [#q08767ad]
-AllCustomersView.xamlで定義。
-CustomerViewModelの一覧が、AllCustomersとして公開されて...
#pre{{
public ObservableCollection<CustomerViewModel> All...
}}
-CustomerRepositoryを監視し、Customerが追加されたタイミン...
#pre{{
void OnCustomerAddedToRepository(object sender, Cu...
{
var viewModel = new CustomerViewModel(e.NewCu...
this.AllCustomers.Add(viewModel);
}
}}
-顧客が選択されたり選択解除されたりしたときのために、Cust...
-CustomerViewModelのIsSelectedが変更された結果OnCustomerV...
#pre{{
void OnCustomerAddedToRepository(object sender, C...
{
var viewModel = new CustomerViewModel(e.NewCu...
this.AllCustomers.Add(viewModel);
}
}}
*ポイント [#o666aeff]
ページ名: