2011年1月5日水曜日

RelayCommandの実装いろいろ MVVM Light Toolkit

MVVM Light ToolkitのRelayCommandの実装方法を色々と紹介する。今回はWPFで実装している。


1、コマンドパラメータなし
何も特別なことはなし
Xaml
<Button Command="{Binding ClickCommand}" 
        Content="Click Me" />

ViewModel
public RelayCommand ClickCommand { get; private set; }
ClickCommand = new RelayCommand(() =>
{
  // Do something...
});


2、コマンドパラメータあり
ItemsControlのDataTemplate内要素のイベントをフックしている。ここでのDataTemplateのDataContextはDataItemになるので、単純にClickCommandをBindingしても期待した動作にはならない。そのためRelativeSrouceで一番上の親要素(Window)までたどってViewModelを取得している。CommandParameterにDataTemplateのDataContextをBindingしている。

Xaml
<ItemsControl ItemsSource="{Binding DataList}">
 <ItemsControol.ItemTemplate>
  <DataTemplate>
   <Button Command="{Binding DataContext.ClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
       CommandParameter="{Binding}"
           Content="Click Me" />
   </DataTemplate> 
 </ItemsControol.ItemTemplate>
</ItemsControl>

ViewModel
public ObservableCollection<DataItem> DataList { get; set; }
public RelayCommand<DataItem> ClickCommand { get; private set; }
ClickCommand = new RelayCommand(x =>
{
  // Do something...
});


3、ICommand以外をBinding
WindowのLoadedイベントなどをBindingしたい場合はEventToCommandを使用する。
・まずXAMLのネームスペースに下記を追加する:
 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
 xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
・後はフックしたいイベントを下記の要領で記述する

Xaml
<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
        DataContext="{Binding ViewModel, Source={StaticResource Locator}}">
  <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <cmd:EventToCommand Command="{Binding WindowLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>

ViewModel
public RelayCommand WindowLoadedCommand{ get; private set; }
WindowLoadedCommand= new RelayCommand(() =>
{
  // Do something...
});


4、ICommand以外をBinding パラメータあり
WindowのClosingイベントなどでパラメータを渡したい場合はPassEventArgsToCommandをTrueに設定する。

Xaml
<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
        DataContext="{Binding ViewModel, Source={StaticResource Locator}}">
  <i:Interaction.Triggers>
        <i:EventTrigger EventName="Closing">
            <cmd:EventToCommand Command="{Binding WindowClosingCommand}" PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>

ViewModel
public RelayCommand WindowClosingCommand<System.ComponentModel.CancelEventArgs>{ get; private set; }
WindowClosingCommand= new RelayCommand(x =>
{
  // Do something...
});

今回解説したようにEventToCommandを使用するとICommandに対応していないイベントもBinding可能となる。Window要素のイベントに限らずどのような要素にも適用できるのでEventToCommandを使用すればコードビハインドを経由してイベントをリレーする必要がなくなる。

0 件のコメント:

コメントを投稿