web-dev-qa-db-ja.com

MVVMを使用した複数選択の管理

MVVMを学習する過程で、WPFとViewModelパターンの基本的な理解を確立しました。リストを提供するときに次の抽象化を使用しており、選択した単一のアイテムに興味があります。

public ObservableCollection<OrderViewModel> Orders { get; private set; }
public ICollectionView OrdersView
{
    get
    {
        if( _ordersView == null )
            _ordersView = CollectionViewSource.GetDefaultView( Orders );
        return _ordersView;
    }
}
private ICollectionView _ordersView;

public OrderViewModel CurrentOrder 
{ 
    get { return OrdersView.CurrentItem as OrderViewModel; } 
    set { OrdersView.MoveCurrentTo( value ); } 
}

次に、WPFのリストに並べ替えとフィルタリングをサポートするとともにOrdersViewをバインドできます。

<ListView ItemsSource="{Binding Path=OrdersView}" 
          IsSynchronizedWithCurrentItem="True">

これは、単一選択ビューに対して非常にうまく機能します。ただし、ビューでの複数選択もサポートし、選択したアイテムのリストにモデルをバインドしたいと思います。

ListView.SelectedItemsをViewModelのバッカープロパティにバインドするにはどうすればよいですか?

59
Paul Alexander

IsSelectedプロパティを子ViewModelに追加します(あなたの場合はOrderViewModel):

public bool IsSelected { get; set; }

コンテナで選択したプロパティをこれにバインドします(この場合はListBoxの場合)。

<ListBox.ItemContainerStyle>
    <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
    </Style>
</ListBox.ItemContainerStyle>

IsSelectedは、コンテナの対応するフィールドに一致するように更新されます。

以下を実行することで、ビューモデルで選択した子を取得できます。

public IEnumerable<OrderViewModel> SelectedOrders
{
    get { return Orders.Where(o => o.IsSelected); }
}
94
Josh G

私はあなたを保証することができます:SelectedItemsはXAMLとして確かにバインド可能ですCommandParameter

この一般的な問題には簡単な解決策があります。動作させるには、[〜#〜] all [〜#〜]以下のルールに従う必要があります。

  1. Ed Ballの提案 に従って、XAMLコマンドのデータバインディングで、CommandParameter属性を定義します[〜#〜] before [〜#〜]Command属性。 これは非常に時間のかかるバグです

    enter image description here

  2. ICommandCanExecuteおよびExecuteメソッドにobject型のパラメーターがあることを確認してください。この方法により、データバインディングのCommandParameterタイプがCommandメソッドのパラメータータイプと一致しない場合に発生するsilencedキャスト例外を防ぐことができます。

    private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)  
    {
         // Your code goes here
    }
    
    private bool OnDeleteSelectedItemsExecute(object SelectedItems)  
    {
        // Your code goes here
    }
    

たとえば、ListView/ListBoxSelectedItemsプロパティをICommandメソッドまたはListView/ListBox自体。すごいですね。

これにより、誰かがSelectedItemsCanExecuteパラメーターとして受け取る方法を見つけるために費やした膨大な時間を費やすことを防ぐことができます。

12
Julio Nobre

添付プロパティを作成してみることができます。

そうすることで、バインドするリストごとにIsSelectedプロパティを追加する必要がなくなります。私はListBoxに対してそれを行いましたが、リストビューで使用するために変更できます。

<ListBox SelectionMode="Multiple"
         local:ListBoxMultipleSelection.SelectedItems="{Binding SelectedItems}" >

詳細: WPF – ListBox SelectedItemsのバインド–添付プロパティVSスタイル

4
MichaelLo

MVVM-LIGHTを使用している場合、次のパターンを使用できます。

https://galasoft.ch/posts/2010/05/handling-datagrid-selecteditems-in-an-mvvm-friendly-manner

特にエレガントではありませんが、少なくとも信頼できるはずです

1
Simon_Weaver