2013-04-18 13 views
7

Utworzono widok drzewa, który modeluje katalogi i pliki na dysku twardym. Każdy element treeviewItem ma pole wyboru, powiązane z właściwością isSelected. To, co chciałbym osiągnąć, to wyświetlenie dla każdego węzła nadrzędnego liczby wybranych plików z łącznej liczby plików (10/12 10 plików na dwunastu wybranych ogółem).Jak filtrować kolekcję po powiązaniu jej z ItemsSource?

Czy istnieje sposób na powiązanie z tym, gdzie nieruchomość jest ...?

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

Czy używasz MVVM? – DHN

+1

W rzeczywistości jestem DHN. –

+1

Czy możesz opublikować swoje ViewModels lub klasy, które są powiązane z TreeView – Jehof

Odpowiedz

11

Nie ma możliwości bezpośredniego przefiltrowania kolekcji w powiązaniu. Jednak WPF umożliwia filtrowanie (i sortowanie i grupowanie) kolekcji za pomocą CollectionViewSource.

Jedno podejście byłoby zdefiniować CollectionViewSource w zasobach swojej ItemTemplate który filtruje ItemsSource uzyskać liczbę elementów, które przechodzą przez filtr wiążący do właściwości Count tej CollectionViewSource. Musisz jednak zdefiniować swój filtr w kodzie źródłowym. Będzie wyglądać mniej więcej tak:

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

A w kodzie:

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

nie testowałem go, ale to powinno działać w ogóle. Nigdy nie wiadomo, z WPF, choć ...

+0

W dół głosowanie ze względu na część kodu z tyłu –

+1

Nie sądzę, że istnieje potrzeba przetestowania tego urządzenia ... – Marc

+0

Co? Nie ma potrzeby testowania jednostkowego tego? Jak sprawdzić, czy działa ta funkcja ? Automatyczne testowanie interfejsu użytkownika? Jest to przywilej ViewModel, aby zawierał bieżący wybór, a nie View. –

-9

Osobiście korzystam następujące ramy http://logofx.codeplex.com/ która wydaje się spełniać wszystkie wymagania (użyj LogoFX.Mini jak wydaje się na tyle do swoich celów). Użyj opcji WrappingCollection.WithSelection jako elementu ItemsSource Użyj wartości SelectionCount jako wartości, którą chcesz wyświetlić. Jeśli zdecydujesz się nie korzystać z frameworka, powinieneś zasubskrybować dla wybranego zdarzenia zmiany poprzez dedykowane zachowanie, utworzyć dedykowaną właściwość zależności i zaktualizować ją za każdym razem, gdy zmieni się wybór.

I ostatnia rzecz: Zdecydowanie unikaj używania kodu z opóźnieniem. Łamie całą zasadę MVVM.

+4

-1 - * Zdecydowanie unikaj używania kodu z opóźnieniem. * - Daj spokój, to po prostu nieprawda. Jeśli to konieczne, możesz użyć kodu z tyłu. Pomyśl o 'CustomControl', nie możesz zaimplementować jednego bez kodu. Ale są też inne powody, gdy kod jest najprostszym rozwiązaniem. Jeśli napiszesz ** Spróbuj, kiedy będziesz mógł uniknąć używania kodu. **, byłbym z tobą. – DHN

+0

+1 dla DHN, uważam się za dość fundamentalistę MVVM, ale to zdecydowanie nie jest prawda. Zachowania to nic innego jak kod bebind przez btw ... – Marc

+0

Rozróżniam formanty, które pochodzą z UserControl (również widoki) i te, które pochodzą z formantu (czyli niestandardowych formantów). Kiedy mówię o niedozwolonym kodowaniu, odnoszę się tylko do pierwszego. A w przypadku widoków MUSI zostać pominięty kod z tyłu. Jak możesz to sprawdzić, skoro jest oparty na kodowaniu? Jeśli funkcja, którą próbujesz zaimplementować, jest czystym wizualnym zachowaniem, jest odpowiednikiem zaimplementowania jej w kodzie źródłowym (nadal nie widzę potrzeby, ponieważ można to zrobić w XAML lub delegować do działania), jeśli jest coś innego, robisz to źle –