2010-01-14 11 views
5

Ho un ViewModel che ha un IsSelected proprietà che mi legano a mio ListView.ItemContainerStyle XAML a un IsSelected proprietà a mio modello di vista.WPF Binding IsSelected al ViewModel non imposta oggetti che non sono stati indicati nella lista

porto in su l'applicazione e popolare la collezione vista del modello (che viene mostrato nel mio ListView), con un sacco di elementi, dicono circa 2000. Poi selezionare tutto nella lista tramite Ctrl-A. Gli elementi nella mia collezione del modello di visualizzazione ottengono solo il set IsSelected per gli articoli che sono visibili nello ListView. Se faccio scorrere verso il basso l'elenco, IsSelected viene impostato per qualsiasi oggetto visualizzato. Se sfoglio tutti gli elementi, tutti gli elementi nel mio modello di vista hanno la proprietà IsSelected impostata su true.

Ecco il mio XAML per il legame del IsSelected nella vista elenco alla mia vista del modello:

<ListView Margin="5" ItemsSource="{Binding FilteredComparisonList}" x:Name="comparisonListView"> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="{x:Type ListBoxItem}"> 
      <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" /> 
     </Style> 
    </ListView.ItemContainerStyle> 
    <ListView.View> 
     <GridView> 
      <GridViewColumn Header="Source filename" DisplayMemberBinding="{Binding ImageFile.BaseFilename}" Width="Auto" /> 
     </GridView> 
    </ListView.View> 
</ListView> 

Perché non è IsSelected per tutti gli articoli nel mio modello di vista impostate su true quando seleziono tutti gli articoli nello ListView?

+0

Tra l'altro, questo è essenzialmente la stessa domanda come questa: http://stackoverflow.com/questions/1273659/virtualizingstackpanel-mvvm-multiple-selection – Charlie

+0

Grazie Charlie, non so come ho perso quel post. Quel post ha una buona soluzione a questo problema che consiste nel passare gli elementi selezionati come CommandParameter invece di mantenere IsSelected nel modello di visualizzazione. – Buck

risposta

3

Questo sta accadendo a causa della virtualizzazione integrata di ListView. Se non hai familiarità con ciò, ciò che significa in pratica è che gli oggetti non diventano reali finché non sono in vista. È possibile disattivare la virtualizzazione del ListView con la seguente proprietà:

VirtualizingStackPanel.IsVirtualizing="False" 

Ma attenzione questo avrà un effetto negativo sulle prestazioni del ListView. Per 2.000 articoli non sarà grave, ma potrebbe essere evidente.

2

I ListBoxItem sono virtualizzati, non esistono finché non vengono generati (quando vengono visualizzati). Tuttavia il ListView sottostante è derivato da ListBox che ha una proprietà SelectedItems. Gli oggetti selezionati sono un elenco di tutti gli elementi selezionati e non un elenco di oggetti ListBox selezionati. Quando viene visualizzato l'oggetto ListBoxItem, la proprietà IsSelected viene impostata in base a se l'elemento (l'elemento visualizzato) si trova nella raccolta di SelectedItems.

Questo è un propblem per il tuo modello di vista, soprattutto se hai bisogno della virtualizzazione (cosa che probabilmente fai per 2000 o più elementi). Sarei interessato alla risposta alla domanda "Come posso associare la mia proprietà IsSelected ai modelli di visualizzazione in base a se un elemento si trova nella raccolta SelectedItems di un ListBox?"

la risposta probabilmente comporta un convertitore

4

Il modo MVVM per farlo sarebbe quello di ignorare il Ctrl-Un collegamento con il proprio comando SelectAll (Creare un comando SellectAll con una scorciatoia Ctrl-A). L'implementazione imposterà IsSelected sui modelli di visualizzazione.

La proprietà IsSelected nella vista dell'utente deve avere un'associazione a due vie per il modello di vista in modo che gli elementi vengano visualizzati nella vista.

Non penso che spegnere la virtualizzazione sia necessario.

Spero che questo aiuti.

0

ho avuto lo stesso problema e questo è ciò che mi ha aiutato, infine:

mettere nel vostro ListView:

VirtualizingStackPanel.VirtualizationMode="Standard" 
0

invierò questa risposta che ho trovato su un forum diverso dal momento che mi ha aiutato con il problema.

ho definito un'interfaccia ISelectable per i miei ViewModels per implementare

public interface ISelectable 
{ 
    bool IsSelected { get; set; } 
} 

Poi nel MyCustomListView ho fatto questo:

public class MyCustomListView : ListView 
{ 
    protected override void OnSelectionChanged(SelectionChangedEventArgs e) 
    { 
     foreach (var item in e.AddedItems.OfType<ISelectable>()) 
      item.IsSelected = true; 

     foreach (var item in e.RemovedItems.OfType<ISelectable>()) 
      item.IsSelected = false; 

     base.OnSelectionChanged(e); 
    } 
} 

In alternativa, si potrebbe fare sottoscrivere l'evento SelectionChanged del ListView e utilizzare lo stesso codice sopra.

Problemi correlati