kazuakix の日記

Windows Phone とか好きです

Windows Phone でListView にコマンドを割り当ててみる

ちょっと検索すればすぐ出てきますね。

こんな感じにトリガーを書けばいいと...

<ListView ItemTemplate="{StaticResource ItemTemplate}"  ItemsSource="{Binding ItemList}"  SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
    <Triggers:Interactions.Triggers>
        <Triggers:EventTrigger EventName="SelectionChanged">
            <Triggers:InvokeCommandAction Command="{Binding SelectedItemCommand}"
                CommandParameter="{Binding SelectedItem,Mode=TwoWay}"/>
        </Triggers:EventTrigger>
    </Triggers:Interactions.Triggers>
</ListView>

いや、これならコードビハインド書くだろ...となりそうなので別の方法を。

Blend でやってみる

まずは普通に見た目だけの画面を作ります。

f:id:kazuakix:20150211174149j:plain

イベントトリガーをつける

アセットのビヘイビアーから EventTriggerBehavior を選んで ListView にドラッグ アンド ドロップします。

f:id:kazuakix:20150211174154j:plain
 
ビヘイビアーのプロパティを見るといろいろなイベントを選択することができます。
今回はデフォルトの SelectionChanged イベントにしておきました。

f:id:kazuakix:20150211174200j:plain
 

アクションをつける

続いて同じくビヘイビアーの一覧から InvokeCommandAction をさっきの EventTriggerBehavior にドラッグ アンド ドロップします。

f:id:kazuakix:20150211174206j:plain
 
プロパティを見ると Command と CommandParameter の欄があるのでそれぞれ指定していきます。

f:id:kazuakix:20150211174212j:plain

Command の指定

まずは Command 。プロパティの右側 □ メニューからデータバインディングの作成を選んで、ViewModel で定義したコマンドを選択します。

f:id:kazuakix:20150211174220j:plain

ちなみに、このコマンドはあらかじめ ViewModel で以下のような感じで定義したうえで Blend でサンプルデータとして作成しています。

/// <summary>スレを選択するコマンド</summary>
public DelegateCommand<SubjectPanelViewModel> SelectThreadCommand { get; set; } 

こうしておくことで Blend の画面上で操作できるようになるのが便利ですね。

CommandParameter の指定

最後に ListView で選択された項目を伝えるために CommandParameter を指定します。
Command と同じくプロパティの右側 □ から 今度は要素にバインドを選んで、画面上の ListView を指定します。

ListView の何とバインドするのか聞いてくるので、SelectecItem を指定してオプションとしてバインドの方向を TwoWay にしておきます。

f:id:kazuakix:20150211174225j:plain

これで ListView の個々のアイテムにバインドされているオブジェクト (この例では SubjectPanelViewModel 型) が Command の引数として渡ってきます。

受け取る ViewModel はこんな感じで OK

public class BoardPageViewModel : ViewModel
{
    /// <summary>スレを選択するコマンド</summary>
    public DelegateCommand<SubjectPanelViewModel> SelectThreadCommand { get; set; } 
    
    public BoardPageViewModel()
    {
        SelectThreadCommand = new DelegateCommand<SubjectPanelViewModel>(SelectThread);
    }
    
    private void SelectThread(SubjectPanelViewModel subject)
    {
        // ListView で subject が選択されたときに呼ばれる
    }
}

完成

この時点でこんな XAML になっていました。最初にみたのとほぼ同じですね。

<ListView x:Name="listView" ItemTemplate="{StaticResource SubjectsDataTemplate}" ItemsSource="{Binding Subjects}">
    <Interactivity:Interaction.Behaviors>
        <Core:EventTriggerBehavior EventName="SelectionChanged" >
            <Core:InvokeCommandAction Command="{Binding SelectThreadCommand}" 
                CommandParameter="{Binding SelectedItem, ElementName=listView}"/>
        </Core:EventTriggerBehavior>
    </Interactivity:Interaction.Behaviors>
</ListView>

まぁ 2 回目からはコードコピペで済ませると思いますが...。