SelectedItemはBindingできるのにSelectedItemsはBindingできなくてもどかしいですよね。
Bindingできないないので利用しない人が多いと思いますが、実はオブジェクトも取り出せますし、使ってみると便利ですよ。
Style.TriggerなどでDataGridの内側からSelectedItemsを参照する
DataGridで複数のRowを選択中、という条件を指定したい場合は多いと思います。
無選択ならボタンがdisableで、1つならable、複数選択の時は別の機能に変えたい、って場合があるとします。
これは1例ですが、選択中かつ選択中のアイテムが1つの時、というのを指定しています。
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="true" />
<Condition Binding="{Binding Path=SelectedItems.Count, RelativeSource={RelativeSource AncestorType=DataGrid}}" Value="1" />
</MultiDataTrigger.Conditions>
IsSelectedプロパティはDataGridRowのプロパティ、
SelectedItemsプロパティはDataGridのプロパティなので、それぞれRelativeSourceで遡れば取得できます。
ContextMenuからSelectedItemsを参照する
SelectedItemsをBehavior経由でBindingする
SelectedItemsをCommandParameterにBindingする
EventToReactiveCommandでEventArgsからSelectedItemsを取得する
Xaml
<UserControl x:Class="TestApp.Views.Controls.TestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.NET46">
<DataGrid ItemsSource="{Binding Items}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<interactivity:EventToReactiveCommand Command="{Binding SelectionChangedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
</UserControl>
ViewModel
public class TestViewModel
{
public TestViewModel()
{
this.SelectedItems= new ObservableCollection<string>()
this.SelectionChangedCommand = new ReactiveCommand<SelectionChangedEventArgs>()
.WithSubscribe(e =>
{
this.SelectedItems.Clear();
var items = ((DataGrid)e.Source).SelectedItems;
foreach(string item in items)
{
this.SelectedItems.Add(item);
}
});
}
public ObservableCollection<string> SelectedItems{ get; set; }
public ReactiveCommand<SelectionChangedEventArgs> SelectionChangedCommand { get; set; }
}
EventToReactiveCommandはコントロールのイベントをCommandとして購読できる機能です。
EventArgsを取得して利用する場合は、ReactiveCommand<T>に該当のEventArgsを指定します。
イベントの購読のみでEventArgsが不要な場合は<T>は設定しなくてOKです。
DataGridのSelectionChangedEventはSelectionChangedEventArgsを使います。
SelectionChangedEventArgsの場合、AddedItemsやRemovedItemsがありますが、これらは既に選択中にCtrlクリック等で新たに追加/削除した場合、追加/削除された項目しか取得できません。
選択中の全件を取得するにはDataGridへの参照が必要になります。
((DataGrid)e.Source).SelectedItems
でEventSourceを取得し、SelectedItemsを取得しています。
EventArgsそのものを渡すとViewModelがViewへの参照を取得できてしまうため、今回の実装はあまり良くありません。必要なSelectedItemsへの参照を渡すだけに限定したい場合は、 ReactiveConverter を使ってReactiveCommandに渡すparameterを加工します。
詳しくは以下の記事を参照してください。
コメント