2011年4月25日月曜日

[MVVM] ViewとViewModelのバインド

とりあえず難しい話は省いていきなり実践で。

【課題】ログインの画面を作りたい。

まず画面から作成する。
[ファイル:LoginDialog.xaml]
<Window x:Class="Tutorial.LoginDialog"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="ログイン" SizeToContent="WidthAndHeight"/>
  <StackPanel>
    <Label>ユーザー名</Label>
    <TextBox Width="150px"/>
    <Label>パスワード</Label>
    <PasswordBox Width="150px"/>
    <StackPanel Orientation="Horizontal">
      <Button IsEnabled="False">ログイン</Button>
      <Button>キャンセル</Button>
    </StackPanel>
  </StackPanel>
</Window>

とりあえず、これで最低限必要なものはそろった。

ビジネスユーザの仕様は以下の通りだとする。
  • このビュー(表示画面)はログインIDとパスワードを入力するためのテキストボックスがある。
  • ユーザはログインとキャンセルの二つの操作ができる。
  • ログインのボタンは、デフォルトで押せないようにする。ユーザがID・パスワードを入力したらボタンが押せるようにする
  • ログインを押した後は、非同期的に認証サーバーに問い合わせて、ユーザーのパーミッションの情報などを引き出す

次にコードビハインドを書く。
[ファイル:LoginDialog.xaml.cs]
public partial class LoginDialog
    {
        public LoginDialog()
        {
            InitializeComponent();
            DataContext = LoginDialogViewModel();
        }
    }
MVVMにおいては原則、コードビハインドには何も書かない。「ViewModelをDataContextプロパティーにアサインする」部分のみ、コードビハインドに記述する。

最後にもうひとつ.csファイルを作る。
[ファイル:LoginDialogViewModel.cs]
public sealed class LoginDialogViewModel : ViewModelBase
    {
        #region Fields
        private string _loginId;
        private string _password;
        #endregion

        #region Bindable Properties
        public string LoginId
        {
            get { return _loginId; }
            set { _loginId = value; NotifyPropertyChange("LoginId");}
        }

        public string Password
        {
            get { return _password; }
            set { _password = value; NotifyPropertyChange("Password");}
        }
        #endregion

        #region Bindable Commands
        public ICommand LoginCommand { get; private set; }

        public ICommand CancelCommand { get; private set; }
        #endregion

        public LoginDialogViewModel()
        {
           ...
        }
    }

なんとなくご覧にいただければわかると思うが、これは先ほどXamlで記述したダイアログが必要とする「情報」と「操作」を平たく抽出していることがわかる。このファイルこそがViewModelで、名前の通りまさに「ViewのためのModel」である。もう一度LoginDialog.xamlに戻って、このViewModelのプロパティーを各Viewの要素にバインドする。

[ファイル:LoginDialog.xaml]
<Window x:Class="Tutorial.LoginDialog"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="ログイン" SizeToContent="WidthAndHeight"/>
  <StackPanel>
    <Label>ユーザー名</Label>
    <TextBox Text="{Binding LoginId}" Width="150px"/>
    <Label>パスワード</Label>
    <PasswordBox Password="{Binding Password}" Width="150px"/>
    <StackPanel Orientation="Horizontal">
      <Button IsEnabled="False" Command="{Binding LoginCommand}">ログイン</Button>
      <Button Command="{Binding CancelCommand}">キャンセル</Button>
    </StackPanel>
  </StackPanel>
</Window>

バインドはこれで完了。これでユーザがIDを入力するとViewModelのLoginIdの値に自動的にインプットされる、というわけだ。次回は、ViewModelの実装を行う。

以下は、すべてのViewModelの雛形となるViewModelBaseの実装。
[ファイル:ViewModelBase.cs]
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChange( string fieldName )
        {
            if( PropertyChanged != null )
            {
                PropertyChanged(this,new PropertyChangedEventArgs(fieldName));
            }
        }
    }

0 件のコメント:

コメントを投稿