VirtualizingStackPanel + MVVM + Mehrfachauswahl
-
16-09-2019 - |
Frage
Ich habe ein Auswahlmuster ähnlich den in diesen Beitrag mit ein Ansichtsmodell des IsSelected Wert zu speichern, und durch die ListViewItem.IsSelected
auf das Ansichtsmodell IsSelected Bindung:
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListView.ItemContainerStyle>
Es funktioniert im Allgemeinen, aber ich begegne ein ernstes Problem. Durch die Verwendung der eine VirtualizingStackPanel
wie die Platte in der Listenansicht nur die sichtbare ListViewItem
erstellt zu werden. Wenn ich „Strg + A“ verwenden, um alle Elemente auszuwählen, oder durch Tastenkombination solche „Shift + Strg + Ende“ auf den ersten Punkt verwenden, erhalten alle Elemente ausgewählt, aber für die nicht sichtbaren Elemente, wird das Ansichtsmodell nicht bekommen seine IsSelected auf true gesetzt. Das ist logisch, denn wenn die ListViewItem
nicht erstellt werden, kann die Bindung nicht.
Jeder erlebt das gleiche Problem und fand eine Lösung (abgesehen von nicht VirtualizingStackPanel
verwenden)?
Lösung
fand ich eine andere Art und Weise Auswahl der MVVM Muster der Handhabung, die mein Problem gelöst. Anstatt die Auswahl im Ansichtsmodell beibehalten wird, wird die Auswahl aus dem Listview / List-Box abgerufen und als Parameter an den Befehl übergeben. Alles in XAML getan:
<ListView
x:Name="_items"
ItemsSource="{Binding Items}" ... />
<Button
Content="Remove Selected"
Command="{Binding RemoveSelectedItemsCommand}"
CommandParameter="{Binding ElementName=_items, Path=SelectedItems}"/>
in meinem Ansichtsmodell:
private void RemoveSelection(object parameter)
{
IList selection = (IList)parameter;
...
}
Andere Tipps
In meinem Fall landete ich diese Lösung durch eine ListBoxEx Klasse von ListBox ableiten, und das Hinzufügen von Code Auswahl Änderungen zu reagieren, den Auswahlzustand auf den Punkt Ansicht Modelle Durchsetzung:
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;
}
}
}
Neben nicht VirtualizingStackPanel
verwenden, das einzige, was ich denken kann, ist diese Tastenkombinationen zu erfassen und haben Methoden für einen bestimmten Bereich Ihrer ViewModel
Artikel zu modifizieren, so dass ihre IsSelected
Eigenschaft auf True
(zB SelectAll()
, SelectFromCurrentToEnd()
) . Im Grunde genommen unter Umgehung des Binding
auf ListViewItem
für die Auswahl für solche Fälle zu steuern.