2013-04-18 7 views
7

Ho creato una vista ad albero che modella directory e file sul mio disco rigido. Ogni treeviewItem ha una casella di controllo, associata a una proprietà isSelected. Quello che mi piacerebbe ottenere è visualizzare per ogni nodo genitore il conteggio dei file selezionati sul totale dei file (10/12 file su 12 totali selezionati).Come filtrare una raccolta quando si lega a ItemsSource?

C'è un modo per eseguire un'associazione con dove la proprietà è ...?

<ContentPresenter Content="{Binding MyItems.Count where MyItems.IsSelected, Mode=OneTime}" 
        Margin="2,0" /> 
+1

Stai utilizzando MVVM? – DHN

+1

In effetti, sono DHN. –

+1

Puoi postare ViewModels o le classi associate al controllo TreeView – Jehof

risposta

11

Non esiste alcun modo per filtrare direttamente la raccolta nell'associazione. Tuttavia, WPF consente di filtrare (e ordinare e raggruppare) raccolte con CollectionViewSource.

Un approccio potrebbe essere quello di definire un CollectionViewSource nelle risorse del vostro ItemTemplate che filtra la ItemsSource un ottenere il numero di elementi che passano il filtro legandosi alla proprietà Count di questo CollectionViewSource. Devi definire il tuo filtro in codebehind, però. Sarebbe simile a questa:

<TreeView x:Name="Tree" ItemsSource="{Binding Items}"> 
    <TreeView.ItemTemplate> 
     <HierarchicalDataTemplate ItemsSource="{Binding ChildItems}"> 
      <HierarchicalDataTemplate.Resources> 
       <CollectionViewSource x:Key="FilteredItems" 
             Source="{Binding ChildItems}" 
             Filter="FilteredItems_OnFilter" /> 
      </HierarchicalDataTemplate.Resources> 
      <TextBlock> 
       <TextBlock.Text> 
        <MultiBinding StringFormat="{} {0} of {1} selected"> 
         <Binding Path="Count" Source="{StaticResource FilteredItems}" /> 
         <Binding Path="ItemsSource.Count" ElementName="Tree" /> 
        </MultiBinding> 
       </TextBlock.Text> 
      </TextBlock> 
     </HierarchicalDataTemplate> 
    </TreeView.ItemTemplate> 
</TreeView> 

E nel codebehind:

private void FilteredItems_OnFilter(object sender, FilterEventArgs e) 
{ 
    var item = sender as Item; 
    e.Accepted = item.IsSelected; 
} 

non ho ancora testato, ma dovrebbe funzionare in generale. Non si sa mai con WPF, anche se ...

+0

Down-voting a causa della parte code-behind –

+1

Non penso che sia necessario testare questa unità ... – Marc

+0

Cosa? Non è necessario testare questa unità? Quindi come si controlla che questa funzionalità di funzioni? Test dell'interfaccia utente automatizzato? È una prerogativa di ViewModel per contenere la selezione corrente, non la vista. –

-9

io personalmente uso il seguente quadro http://logofx.codeplex.com/ che sembra soddisfare tutte le vostre esigenze (utilizzare LogoFX.Mini come sembra sufficiente per i vostri scopi). Usa WrappingCollection.WithSelection come ItemsSource Usa SelectionCount come valore che vuoi visualizzare. Se si decide di non utilizzare il framework, è necessario sottoscrivere l'evento modificato di selezione tramite comportamento dedicato, creare una proprietà di dipendenza dedicata e aggiornarlo ogni volta che la selezione cambia.

E un'ultima cosa: Sicuramente evitare l'uso di code-behind. Rompe l'intero principio MVVM.

+4

-1 - * Evita decisamente l'uso di code-behind. * - Dai, è semplicemente falso. Se necessario, puoi usare il codice dietro. Pensa a un 'CustomControl', non sei in grado di implementarlo senza codice. Ma ci sono vari altri motivi, quando il codice dietro è la soluzione più semplice. Se dovessi scrivere ** Prova quando mai puoi evitare di usare il codice. **, sarei con te. – DHN

+0

+1 per DHN, mi considero un fondamentalista MVVM, ma non è assolutamente vero. I comportamenti non sono altro che codebehind by btw ... – Marc

+0

Distinguiamo tra i controlli derivati ​​da UserControl (ovvero le viste) e quelli derivati ​​dal controllo (ovvero i controlli personalizzati). Quando parlo di code-behind mi riferisco solo al primo. E nel caso di visualizzazioni DEVE essere evitato il code-behind. Come fai a testare una cosa del genere se è costruita su code-behind? Se la funzione che si sta tentando di implementare è un puro comportamento visivo, è equivalente implementarla in un code-behind (ancora non ne vedo la necessità, perché è possibile farlo in XAML o delegarlo a un comportamento), se è qualcos'altro, lo stai facendo in modo sbagliato –

Problemi correlati