#原因
ほとんどのWPFのリストコントロール(DataGridやListView等)は既定で仮想化されており、描画範囲外のコントロールが存在しません。
このため、コントロールベースでこの手の操作を実装をしようとすると失敗します。
#対策
対策は2つあります。1つはアイテムコンテナの仮想化を止めること、もう1つはデータバインディングによって選択済みのアイテムを取得することです。基本的には後者の方がパフォーマンス上ベターです。
#サンプル
データバインディングを使用した選択行を取得する方法を紹介します。どこまでMVVMに準拠するのかによってコーディングは変わってきますが、今回ご紹介するのは最も簡単と思われる方法です。必要であればこちらをBehavior等にすると良いでしょう。
CommandParameterにDataGridのSelectedItemsをバインドすると、選択されたItemのコレクションを取得できます。
XML
1<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding Items}">
2 <i:Interaction.Triggers>
3 <!-- 下記のようにすればMouseRightButtonUpイベントとバインドできます -->
4 <i:EventTrigger EventName="MouseRightButtonUp">
5 <i:InvokeCommandAction
6 Command="{Binding ShowSelectedCommand}"
7 CommandParameter="{Binding ElementName=MyDataGrid, Path=SelectedItems}" />
8 </i:EventTrigger>
9 </i:Interaction.Triggers>
10</DataGrid>
Presenter/ViewModelクラス上の実装
C#
1public ICommand ShowSelectedCommand
2{
3 get
4 {
5 // DelegateCommandは一般的なICommand実装を想定していますが、分からなければ再度聞いてください
6 return _ShowSelectedCommand = _ShowSelectedCommand ??
7 new DelegateCommand(showSelected);
8 }
9}
10private ICommand _ShowSelectedCommand;
11
12private void showSelected(object parameter)
13{
14 // SelectedItemsの型はSelectedItemCollectionという型ですが非公開です
15 // IList型に一旦キャストした後、Castメソッドで目的のコレクションに変換します。
16 var items = (parameter as IList)?.Cast<MyItem>();
17 if (items != null)
18 {
19 // このようにすれば、MyItemsから選択されたMyItemの一覧を取得できます。
20 // ここで目的のItemのIsSelectedプロパティをtrueに設定すれば良いでしょう。
21 MessageBox.Show(string.Join(",", items.Select(item => item.Index)));
22 }
23}
サンプルはSystem.Windows.Interactivityを使用しています。
プロジェクトの参照にSystem.Windows.Interactivityを追加し、XAMLのWindow/UserControlには以下の名前空間を定義してください。
XML
1<Window ...
2 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
3/>
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/12/13 03:28
退会済みユーザー
2016/12/15 01:34
2016/12/15 01:54
2016/12/15 02:26
退会済みユーザー
2016/12/15 05:06
2016/12/15 05:11