WPFã§ã¯ãå¼·åãªãã¼ã¿ãã¤ã³ãã£ã³ã°ãæ´»ãããè¨è¨ãã¿ã¼ã³ã¨ãã¦Model View ViewModelãã¿ã¼ã³ã¨ããã¢ããªã±ã¼ã·ã§ã³ãè¨è¨ããããã§ã®å®ç³ã¨ãªãè¨è¨ãã¿ã¼ã³ãããã¾ããModel View ViewModelãã¿ã¼ã³ã¯MVVMãã¿ã¼ã³ã¨ç¥ããã¾ããMVVMãã¿ã¼ã³ã¯ãWPFã ãã§ãªãWebã¢ããªéçºãããã®ä»ã®ã¢ããªéçºã«ãæ³¢åãã¦ãã¦ãããããã®ç¶æ³ã«å¿ãã¦å½¢ãå¤ãã¦åå¨ãã¦ãã¾ãã MVVMãã¿ã¼ã³ã¯ãMSDNãã¬ã¸ã³ã®ä»¥ä¸ã®è¨äºããã£ããã«ä¸éã«èªç¥ãããããã«ãªãã¾ããã
- Model-View-ViewModel ãã¶ã¤ã³ ãã¿ã¼ã³ã«ãã WPF ã¢ããªã±ã¼ã·ã§ã³ : http://msdn.microsoft.com/ja-jp/magazine/dd419663.aspx
ã¾ããMicrosoftã¯ãªã¼ãã³ã½ã¼ã¹ã§Prismã¨ããMVVMãã¿ã¼ã³ããµãã¼ãããã©ã¤ãã©ãªãæä¾ãã¦ãã¾ãã
ããã§ã¯ãç°¡åã«MVVMãã¿ã¼ã³ã®èãã«ã¤ãã¦èª¬æãããã¨ãPrismã®ä¸é¨ã®æ©è½ã使ã£ã¦å®éã«MVVMãã¿ã¼ã³ã®ãµã³ãã«ããã°ã©ã ãä½æãã¦ããããã¨æãã¾ãã
MVVMãã¿ã¼ã³ã¨ã¯
MVVMãã¿ã¼ã³ã¯ãViewï¼XAML + ã³ã¼ãããã¤ã³ãï¼ã¨ViewModelã¨å¼ã°ããModelãViewã«é©ããã¤ã³ã¿ã¼ãã§ã¼ã¹ã«å¤æããã¬ã¤ã¤ã¨ãã¢ããªã±ã¼ã·ã§ã³ãè¨è¿°ããModelã®ã¬ã¤ã¤ãããªãã¾ããViewã¨ViewModeléã¯ãåºæ¬çã«ãã¼ã¿ãã¤ã³ãã£ã³ã°ã«ãã£ã¦é£æºãè¡ãã¾ããViewModelã¯Modelã®å¤æ´ãç£è¦ããããå¿ è¦ã«å¿ãã¦Modelã®ã¡ã½ããã®å¼ã³åºããè¡ãã¾ãããã®é¢ä¿ãå³ã§è¡¨ãã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
å¤æ´éç¥ã®ä»çµã¿
MVVMãã¿ã¼ã³ã®ãå¤æ´éç¥ãåæ¹åãã¼ã¿ãã¤ã³ãã£ã³ã°ã®ViewModelããViewæ¹åã®å¤æ´éç¥ã«ã¯INotifyPropertyChangedã¤ã³ã¿ã¼ãã§ã¼ã¹ãå®è£ ããã¯ã©ã¹ã使ç¨ãã¾ããINotifyPropertyChangedã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯PropertyChangedã¤ãã³ãã®ã¿ããã¤ã·ã³ãã«ãªã¤ã³ã¿ã¼ãã§ã¼ã¹ã§ãããã®ã¤ãã³ããéãã¦ModelããViewModelãViewModelããViewã¸ã®å¤æ´éç¥ãè¡ããã¾ãã
INotifyPropertyChangedã¤ã³ã¿ã¼ãã§ã¼ã¹ã®å®è£ ããã¹ã¦ã®ããããã£ã«å®è£ ããã®ã¯è² è·ãé«ããããä¸è¬çã«ä»¥ä¸ã®ãããªãã«ãã¼ã¯ã©ã¹ãä½æããã¾ãã
using System.ComponentModel; using System.Runtime.CompilerServices; namespace MVVMSample01 { public class BindableBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null) { if (Equals(field, value)) { return false; } field = value; var h = this.PropertyChanged; if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); } return true; } } }
ãã®ã¯ã©ã¹ãç¶æ¿ããã¨ãããããã£ã®å¤æ´éç¥æ©è½ãæã£ãã¯ã©ã¹ã以ä¸ã®ããã«ç°¡åã«ä½æã§ãã¾ãã
namespace MVVMSample01 { public class Person : BindableBase { private int age; public int Age { get { return this.age; } set { this.SetProperty(ref this.age, value); } } private string name; public string Name { get { return this.name; } set { this.SetProperty(ref this.name, value); } } } }
åä¸ã®ã¯ã©ã¹ã®å¤æ´éç¥ã¯INotifyPropertyChangedã¤ã³ã¿ã¼ãã§ã¼ã¹ã§è¡ãã¾ãããã³ã¬ã¯ã·ã§ã³ã®å¤æ´éç¥ã«ã¯ãããã¾ã§ã使ã£ã¦ããObservableCollection
ã¦ã¼ã¶ã¼ããã®å ¥åã®å¦ç
ãã¿ã³ãã¯ãªãã¯ãããªã©ã®ã¦ã¼ã¶ã¼ã®å¦çãViewããViewModelã«ä¼ããã«ã¯ãCommandã使ç¨ãã¾ãããã®æ使ç¨ããCommandã¯RoutedCommandã§ã¯ãªããããªã²ã¼ãã«Executeã¨CanExecuteå¦çã移è²ããå®è£ ã®DelegateCommandï¼RelayCommandã¨ããååã§ä½ããããã¨ãå¤ãã§ãï¼ã¯ã©ã¹ã使ç¨ãã¾ããDelegateCommandãViewModelã¯ã©ã¹ã®ããããã£ã¨ãã¦å®ç¾©ãã¦ãViewã®ButtonãMenuItemãªã©ã®Commandããããã£ã¨ãã¤ã³ããã¦ä½¿ç¨ãã¾ãã
æåã®ã¢ããªã±ã¼ã·ã§ã³ã®ä½æ
åã¬ã¤ã¤ã®é£æºæ¹æ³ãããã£ãã®ã§ãç°¡åãªã¢ããªã±ã¼ã·ã§ã³ãä½æãã¾ãããã®ã¢ããªã±ã¼ã·ã§ã³ã¯ãå ¥åããæååãããã¿ã³ãæ¼ããã¿ã¤ãã³ã°ã§å¤§æåã«å¤æãã¦åºåãããã®ã§ãããã¿ã³ã¯ãå ¥åã空ã®å ´åã¯æ¼ããã¨ãã§ãã¾ãããã¾ãããã®ãµã³ãã«ããã°ã©ã ã¯ãå¦çãåç´ãããããModelã«è©²å½ããé¨åã¯åå¨ãã¾ãããããã¾ã§Viewã¨ViewModelãé£æºããå ´åã®åãã示ããã®ã§ãã
WPFã¢ããªã±ã¼ã·ã§ã³ãä½æãã¦NuGetã§Prism.Mvvmã®ããã±ã¼ã¸ã追å ãã¾ããPrism.Mvvmã¯BindableBaseã¯ã©ã¹ãDelegateCommandã¯ã©ã¹ãªã©ã®MVVMãã¿ã¼ã³ã«å¿ é ã®ã¯ã©ã¹ã ããæã£ãã·ã³ãã«ãªã©ã¤ãã©ãªã§ãã
ã©ã¤ãã©ãªã追å ããããViewModelãä½æãã¾ããMainWindowViewModelã¨ããååã§ã¯ã©ã¹ãä½ã£ã¦ä»¥ä¸ã®ãããªã³ã¼ããä½æãã¾ããå ¥åç¨ã®ããããã£ã¨åºåç¨ã®ããããã£ã¨å¤æç¨ã®ã³ãã³ããå®ç¾©ãã¦ãã¾ããã³ãã³ãã®å®è¡å¯å¦ã¯ãå ¥åå¤ãå¤åãããã³ã«è©ä¾¡ãå¿ è¦ãªã®ã§DelegateCommandã®CanExecuteãåè©ä¾¡ããããã®ã¡ã½ãããå¼ã³åºãã¦ãã¾ãã
ã¯ã©ã¹ãå®ç¾©ãã¾ãã
using Microsoft.Practices.Prism.Commands; using Microsoft.Practices.Prism.Mvvm; namespace MVVMSample01 { public class MainWindowViewModel : BindableBase { } }
å ¥åãåºåãåãåãããããã£ãå®ç¾©ãã¾ãã
private string input; /// <summary> /// å ¥åå¤ /// </summary> public string Input { get { return this.input; } set { this.SetProperty(ref this.input, value); // å ¥åå¤ã«å¤ãããã度ã«ã³ãã³ãã®CanExecuteã®ç¶æ ãå¤ãã£ããã¨ãéç¥ãã this.ConvertCommand.RaiseCanExecuteChanged(); } } private string output; /// <summary> /// åºåå¤ /// </summary> public string Output { get { return this.output; } set { this.SetProperty(ref this.output, value); } }
ããã¦ãCommandãå®ç¾©ãã¾ãã
/// <summary> /// å¤æã³ãã³ã /// </summary> public DelegateCommand ConvertCommand { get; private set; } public MainWindowViewModel() { // å¤æã³ãã³ãã«å®éã®å¦çããããã¦åæå this.ConvertCommand = new DelegateCommand( this.ConvertExecute, this.CanConvertExecute); } /// <summary> /// 大æåã«å¤æ /// </summary> private void ConvertExecute() { this.Output = this.Input.ToUpper(); } /// <summary> /// ä½ãå ¥åããã¦ããå®è¡å¯è½ /// </summary> /// <returns></returns> private bool CanConvertExecute() { return !string.IsNullOrWhiteSpace(this.Input); }
ãã«ããã¦Viewï¼XAMLï¼ãä½æãã¾ããViewModelãXAMLã§åç §ã§ããããã«åå空éã®å®ç¾©ãè¡ãã¾ãã
xmlns:l="clr-namespace:MVVMSample01"
ããã¦ãDataContextããããã£ã«å ã»ã©ä½æããViewModelã¯ã©ã¹ãè¨å®ãã¾ãã
<Window.DataContext> <l:MainWindowViewModel /> </Window.DataContext>
ç»é¢ãä½æãã¦ããã¾ããå ¥åç¨ã®TextBoxã¨åºåç¨ã®TextBlockã¨ã³ãã³ããå®è¡ããããã®Buttonãç½®ãã¦ãViewModelã®å¯¾å¿ããããããã£ã¨ãã¤ã³ãã£ã³ã°ãã¦ãã¾ãã
<Window x:Class="MVVMSample01.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:l="clr-namespace:MVVMSample01" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <l:MainWindowViewModel /> </Window.DataContext> <StackPanel> <TextBox Text="{Binding Input, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> <Button Content="Convert" Command="{Binding ConvertCommand}" /> <TextBlock Text="{Binding Output}" /> </StackPanel> </Window>
å®è¡ããã¨ã以ä¸ã®ãããªç»é¢ã表示ããã¾ãã
TextBoxã«æåãå ¥åããã¨Convertãã¿ã³ãæ¼ããããã«ãªããæ¼ãã¨Convertãã¿ã³ã®ä¸ã«å¤§æåã«å¤æãããçµæã表示ããã¾ãã
éå»è¨äº
- WPF4.5入門 その1 「はじめに」
- WPF4.5入門 その2 「WPFとは」
- WPF4.5入門 その3 「Hello world」
- WPF4.5入門 その4 「Mainメソッドはどこにいった?」
- WPF4.5入門 その5 「全てC#でHello world」
- WPF4.5入門 その6 「WPFを構成するものを考えてみる」
- WPF4.5入門 その7 「XAMLのオブジェクト要素と名前空間」
- WPF4.5入門 その8 「オブジェクト要素のプロパティ」
- WPF4.5入門 その9 「コレクション構文」
- WPF4.5入門 その10 「コンテンツ構文」
- WPF4.5入門 その11 「マークアップ拡張」
- WPF4.5入門 その12 「その他のXAMLの機能」
- WPF4.5入門 その13 「簡単なレイアウトを行うコントロール」
- WPF4.5入門 その14 「レイアウトコントロールのCanvasとStackPanel」
- WPF4.5入門 その15 「レイアウトコントロールのDockPanelとWrapPanel」
- WPF4.5入門 その16 「ViewBoxコントロール」
- WPF4.5入門 その17 「ScrollViewerコントロール」
- WPF4.5入門 その18 「Gridコントロール part 1」
- WPF4.5入門 その19 「Gridコントロール part 2」
- WPF4.5入門 その20 「レイアウトに影響を与えるプロパティ」
- WPF4.5入門 その21 「WPFのコンセプトと重要な機能つまみ食い」
- WPF4.5入門 その22 「Buttonコントロール」
- WPF4.5入門 その23 「DataGridコントロール その1」
- WPF4.5入門 その24 「DataGridコントロール その2」
- WPF4.5入門 その25 「TreeViewコントロール その1」
- WPF4.5入門 その26 「TreeViewコントロール その2」
- WPF4.5入門 その28 「Calendarコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その29 「ContextMenuコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その30「Menuコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その31 「ToolBarコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その32 「CheckBoxコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その33 「ComboBoxコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その34 「ListBoxコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その35 「RadioButtonコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その36 「Sliderコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その37 「TabControl」 - かずきのBlog@hatena
- WPF4.5入門 その38 「ファイルダイアログ」 - かずきのBlog@hatena
- WPF4.5入門 その39 「情報を表示するコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その40 「Popup、ToolTip、TextBox、Image、MediaElementコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その41 「DispatcherObject」 - かずきのBlog@hatena
- WPF4.5入門 その42 「WPFのプロパティシステム」 - かずきのBlog@hatena
- WPF4.5入門 その43 「読み取り専用の依存関係プロパティ」 - かずきのBlog@hatena
- 拡張されたプロパティメタデータ - かずきのBlog@hatena
- WPF4.5入門 その45 「添付プロパティ」 - かずきのBlog@hatena
- WPF4.5入門 その46 「WPFのイベントシステム」 - かずきのBlog@hatena
- WPF4.5入門 その47 「コンテンツモデル」 - かずきのBlog@hatena
- WPF4.5入門 その48 「WPFのアニメーション その1」 - かずきのBlog@hatena
- WPF4.5入門 その49 「WPFのアニメーション その2」 - かずきのBlog@hatena
- WPF4.5入門 その50 「Style」 - かずきのBlog@hatena
- WPF4.5入門 その51 「リソース」 - かずきのBlog@hatena
- WPF4.5入門 その52 「コントロールテンプレート」 - かずきのBlog@hatena
- WPF4.5入門 その53 「ユーザーコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その54 「カスタムコントロール」 - かずきのBlog@hatena
- WPF4.5入門 その55 「Binding その1」 - かずきのBlog@hatena
- WPF4.5入門 その56「コレクションのバインディング」 - かずきのBlog@hatena
- WPF4.5入門 その57「コマンド」 - かずきのBlog@hatena
- WPF4.5入門 その58「Behavior」 - かずきのBlog@hatena
- WPF4.5入門 その59「Behaviorの自作」 - かずきのBlog@hatena