ICommandインターフェイスの実装を簡略化する

前回私のブログ(http://azumal.hatenablog.com/entry/2014/04/13/105502)で MVVM のサンプルプログラムを公開しました。

サンプルの中で ICommand インターフェイスを実装したクラスを定義していましたが、下記の記事を読んで、もっと簡単に実装できることがわかりました。

 

「Model-View-ViewModel デザイン パターンによる WPF アプリケーション」

http://msdn.microsoft.com/ja-jp/magazine/dd419663.aspx#id0090030

 

上記記事で紹介されている RelayCommand クラスを利用することで、

コマンドの定義を簡略化することができます。

 

「MainWindowViewModel」クラス(RelayCommand での実装)

public class MainWindowViewModel {
        public Person RegisteredPerson { get; set; }
        public ObservableCollection<Person> People { get; set; }
        public ICommand RegisterPersonCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public List<Sexes> Roles { get; set; }

        public MainWindowViewModel() {
            People = new ObservableCollection<Person>();
            RegisteredPerson = new Person();
            RegisterPersonCommand = new RelayCommand(param => this.RegisterPerson(param));
            CancelCommand = new RelayCommand(param => this.Cancel(param));
        }

        public void RegisterPerson(object parameter) {
            var p = (Person)parameter;
            People.Add(new Person(p.PersonID, p.FirstName, p.LastName, p.Sex, p.BirthDay));
            RegisteredPerson.PersonID++;
            RegisteredPerson.FirstName = string.Empty;
            RegisteredPerson.LastName = string.Empty;
            RegisteredPerson.Sex = Sexes.男性;
            RegisteredPerson.BirthDay = DateTime.Today;
        }

        public void Cancel(object parameter) {
            var p = (Person)parameter;
            p.PersonID = People.Max<Person>(u => u.PersonID) + 1;
            p.FirstName = string.Empty;
            p.LastName = string.Empty;
            p.Sex = Sexes.男性;
            p.BirthDay = DateTime.Today;
        }
    }

「MainWindowViewModel」クラス(前回ブログより ICommand での実装)

public class MainWindowViewModel {
        public Person RegisteredPerson { get; set; }
        public ObservableCollection<Person> People { get; set; }
        public ICommand RegisterPersonCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public List<Sexes> Roles { get; set; }

        public MainWindowViewModel() {
            People = new ObservableCollection<Person>();
            RegisteredPerson = new Person();
            RegisterPersonCommand = new RegisterPerson(this);
            CancelCommand = new Cancel(this);
        }
    }

    public class RegisterPerson : ICommand {
        private ObservableCollection<Person> _people;
        private Person _person;
        public RegisterPerson(MainWindowViewModel view) {
            _people = view.People;
            _person = view.RegisteredPerson;
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            var p = (Person)parameter;
            _people.Add(new Person(p.PersonID, p.FirstName, p.LastName, p.Sex, p.BirthDay));
            _person.PersonID++;
            _person.FirstName = string.Empty;
            _person.LastName = string.Empty;
            _person.Sex = Sexes.男性;
            _person.BirthDay = DateTime.Today;
        }
    }

    public class Cancel : ICommand {
        private ObservableCollection<Person> _people;
        public Cancel(MainWindowViewModel view) {
            _people = view.People;
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            var p = (Person)parameter;
            p.PersonID = _people.Max<Person>(u => u.PersonID) + 1;
            p.FirstName = string.Empty;
            p.LastName = string.Empty;
            p.Sex = Sexes.男性;
            p.BirthDay = DateTime.Today;
        }
    }

 いかがでしょうか。

RelayCommand クラスを定義しておくだけで、コマンドのために実装するコード量が削減されたと共に、MainWindowViewModel クラスにコマンドの実装が内包されています。MSDN マガジンに感謝です!