2009-08-13 14 views
22

IはIsSelected値を格納するビューモデルを使用して、this postに記載したものと同様の選択パターンを実装し、ビューモデルIsSelectedにListViewItem.IsSelectedを結合させた:VirtualizingStackPanel + MVVM +複数選択

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

それが動作します一般的に、私は重大な問題に遭遇します。リストビューのパネルとしてVirtualizingStackPanelを使用すると、表示されるのはListViewItemのみになります。 「Ctrl + A」を使用してすべての項目を選択するか、最初の項目で「Shift + Ctrl + End」などのショートカットの組み合わせを使用すると、すべての項目が選択されますが、非表示項目の場合、ViewModelはIsSelected trueに設定します。これは論理的です。ListViewItemが作成されていないと、バインディングは機能しません。

誰も同じ問題を経験し、解決策を見つけました(VirtualizingStackPanelを使用していない場合を除きます)。

+0

は、この問題のために、この完全なソリューションをお試しくださいhttp://stackoverflow.com/a/29545790 – nvkokorin

答えて

28

私の問題を解決したMVVMパターンの選択を処理する別の方法が見つかりました。ビューモデル内の選択を維持する代わりに、選択はListView/ListBoxから取得され、パラメータとしてコマンドに渡されます。すべてのXAMLで行わ:

<ListView 
    x:Name="_items" 
    ItemsSource="{Binding Items}" ... /> 

<Button 
    Content="Remove Selected" 
    Command="{Binding RemoveSelectedItemsCommand}" 
    CommandParameter="{Binding ElementName=_items, Path=SelectedItems}"/> 

私のViewModelに:私の場合は

private void RemoveSelection(object parameter) 
{ 
    IList selection = (IList)parameter; 
    ... 
} 
+5

私はこの方法が気に入っていますが、この方法でビューモデルから項目をプログラムで選択することはできません。 –

+1

ListViewとボタンが異なるユーザーコントロールのスコープにある場合、これも機能しません。 –

1

別にVirtualizingStackPanelを使用していないから、私は考えることができる唯一のことは、これらのキーボードショートカットをキャプチャし、そのIsSelectedプロパティがTrue(例えば、SelectAll()SelectFromCurrentToEnd()に設定されているように、あなたのViewModel項目の特定の範囲を変更するためのメソッドを持つことです)。基本的にBindingListViewItemにバイパスして、そのような場合の選択を制御します。

+2

これはキーボードやマウスで起こるさまざまな方法を忘れないでください! Ctrl + A、Shift + End、Shift + Homeを選択すると、マウスで任意の範囲をShift +クリックできます。これらすべてが同じ問題を引き起こす可能性があります。 – Qwertie

3

、私は強制、リストボックスからListBoxExクラスを派生し、選択の変化に対応するためのコードを追加することで、これを解決することになりましたアイテムビューモデルの選択状態: :

private readonly List<IListItemViewModelBase> selectedItems = new List<IListItemViewModelBase>(); 

protected override void OnSelectionChanged(SelectionChangedEventArgs e) 
{ 
    base.OnSelectionChanged(e); 

    bool isVirtualizing = VirtualizingStackPanel.GetIsVirtualizing(this); 
    bool isMultiSelect = (SelectionMode != SelectionMode.Single); 

    if (isVirtualizing && isMultiSelect) 
    { 
     var newSelectedItems = SelectedItems.Cast<IListItemViewModelBase>(); 

     foreach (var deselectedItem in this.selectedItems.Except(newSelectedItems)) 
     { 
      deselectedItem.IsSelected = false; 
     } 

     this.selectedItems.Clear(); 
     this.selectedItems.AddRange(newSelectedItems); 

     foreach (var newlySelectedItem in this.selectedItems) 
     { 
      newlySelectedItem.IsSelected = true; 
     } 
    } 
}