Domanda

Ho implementato un modello selezione simile a quello descritto in questo post utilizzando un ViewModel per memorizzare il valore IsSelected, e legandosi al ListViewItem.IsSelected al ViewModel IsSelected:

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

Funziona in generale, ma ho incontrato un problema grave. Usando il un VirtualizingStackPanel come il pannello nella visualizzazione elenco, sono sempre creato solo l'ListViewItem visibile. Se uso "Ctrl + A" per selezionare tutti gli elementi, o usando combinazione di tasti come "Shift + Ctrl + Fine" sul primo elemento, tutti gli elementi vengono selezionati, ma per gli articoli non visibili, il ViewModel non ottiene la sua IsSelected impostata su true. Questo è logico, perché se il ListViewItem non vengono creati, il legame non può funzionare.

Chiunque ha sperimentato lo stesso problema, e ha trovato una soluzione (oltre a non utilizzare un VirtualizingStackPanel)?

È stato utile?

Soluzione

Ho trovato un altro modo di gestire la selezione nel modello MVVM, che ha risolto il mio problema. Invece di mantenere la selezione nel ViewModel, la selezione viene recuperato dal ListView / ListBox, e passato come parametro al Comando. Tutto fatto in XAML:

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

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

nel mio ViewModel:

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

Altri suggerimenti

Nel mio caso, ho finito per la soluzione di questo derivando una classe ListBoxEx da ListBox, e l'aggiunta di codice per rispondere ai cambiamenti di selezione, far rispettare lo stato di selezione sui modelli vista elementi:

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;
        }
    }
}

Oltre a non utilizzare VirtualizingStackPanel, l'unica cosa che mi viene in mente è quello di catturare i tasti di scelta rapida e hanno metodi per modificare una certa gamma dei tuoi articoli ViewModel in modo che la loro proprietà IsSelected è impostato su True (ad esempio, SelectAll(), SelectFromCurrentToEnd()) . Fondamentalmente bypassando il Binding su ListViewItem per controllare la selezione di tali casi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top