poniedziałek, 24 grudnia 2012

70-511 Rozdział 7 - Binding - Sortowanie, Grupowanie oraz Filtrowanie

Sortowanie
Sortowanie zbindowanych danych z kontrolką umożliwia interfejs ICollectionView. Po pobraniu do niego referencji mamy dostęp do kolekcji SortDescriptions, która zawiera obiekty typu SortDescription. Obiekty te definiują po której właściwości dotyczą oraz kierunek sortowania. Umieszczając więcej niż jedną definicję sposobu sortowania, będzie ono miało takie samo znaczenie jak w przypadku zapytań SQL: kolekcja najpierw zostanie posortowana według pierwszego parametru a następnie według drugiego.

Code:
            var collectionView = CollectionViewSource.GetDefaultView(DataContext);
            collectionView.SortDescriptions.Add(new SortDescription("Price", ListSortDirection.Ascending));
            collectionView.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));

Efekt:



Jeżeli bindujemy do źródła, które nie implementuje interfejsu IBindingList, możemy napisać własne porównywanie obiektów a następnie przypisać je do właściwości CustomSort.

Własny mechanizm porównywania opiera się stworzenie klasy która implementuje interfejs IComparer. następnie rzutujemy ICollectionView na ListCollectionView i przypisujemy do właściwości CustomSort obiekt naszej klasy:

Code:
            var collectionView = (ListCollectionView)CollectionViewSource.GetDefaultView(DataContext);
            collectionView.CustomSort = new CustomComparer();



Grupowanie
Kolejną operacją którą oferuje ICollectionView jest grupowanie. Grupy tworzymy poprzez dodanie do kolekcji GroupDescriptions obiektu klasy PropertyGroupDescription. Aby zobaczyć efekt należy jeszcze stworzyć styl wyświetlania dla zgrupowanych obiektów GroupStyle:
Obiekt GroupStyle zawiera następujące właściwości:
  • ContainerStyle - styl dla grupy
  • ContainerStyleSelector - logika wyboru stylu dla grupy
  • HeaderTemplate - styl nagłówka dla grupy
  • HeaderTemplateSelector - logika wybierania stylu dla nagłówka grupy
  • Panel - styl dla panelu, na którym są prezentowane grupowane elementy

Prosty przykład grupowania książek na podstawie ich ceny:

Code:
        <ListBox ItemsSource="{Binding}" Name="lbBooks" ItemTemplate="{StaticResource BooksTemplate}">
            <ListBox.GroupStyle>
                <GroupStyle>
                    <GroupStyle.HeaderTemplate>
                        <DataTemplate>
                            <Label Content="{Binding Path=Name}" Foreground="Purple" Background="Red" Padding="4" />
                        </DataTemplate>
                    </GroupStyle.HeaderTemplate>
                </GroupStyle>
            </ListBox.GroupStyle>
        </ListBox>

Code:
collectionView.GroupDescriptions.Add(new PropertyGroupDescription("Price"));


Efekt:


W HeaderTemplate Label bindowany jest do właściwości Name. Właściwość ta jest pobierana z obiektu klasy PropertyGroupDescription.



Filtrowanie
ICollectionView posiada wbudowany mechanizm filtrowania poprzez właściwość Filter. Jest to delegata ktra przyjmuje jako parametr obiekt i zwraca wartość logiczną.
Przykładowa implementacja, odfiltrowująca książki które kosztują ponad 5 zł:

Code:
            collectionView.Filter += o =>
                                         {
                                             var book = (Book) o;
                                             return book.Price < 5;
                                         };

Efekt:




Filtrowanie obiektów ADO.NET
Metoda wyżej opisana nie zadziała na obiekty związane z ADO.NET (DataSet, Table). Jest to spowodowane tym, iż tak naprawdę bindujemy się do obiektu typu DataView. DataView posiada własny mechanizm filtrowania. Możemy z niego skorzystać poprzez właściwość BindingListCollectionView.CustomFilter. Właściwość ta przyjmuje parametr jako łańcuch w formacie:
<ColumnName> <Operator> <Value>
Przykładowo jeżeli chcemy odfiltrować osoby których imię to Lucy, wystarczy napisać:
FirstName = 'Lucy'
W przypadku wartości łańcuchowych zamykamy je w apostrofach.
Przykład w kodzie:

Code:
            var customersCollectionView =
                (BindingListCollectionView)CollectionViewSource.GetDefaultView(((DataContextContent) DataContext).Customers);
            customersCollectionView.CustomFilter = "FirstName = 'Lucy'";


Kod prezentowanych przykładów: http://sdrv.ms/Wl1Yb7

Brak komentarzy:

Prześlij komentarz