Prezentacja zbioru danych za pomocą kontrolki DataGrid

Kontrolka Comarch.POS.Presentation.Core.Controls.DataGrid bazuje na tej znanej z .NET i pozwala na prezentację kolekcji danych, podzielonej na kolumny oraz wiersze. Kontrolka DataGrid w POS dodatkowo pozwala na asynchroniczne pozyskiwanie danych, wspiera stronicowanie listy (doczytywanie danych w trakcie przewijania listy), zmienia sposób realizacji sortowania danych oraz modyfikuje mechanizm grupowania wzbogacając go o agregację danych.

Asynchroniczne pobieranie danych

Aby dane zostały pobrane asynchronicznie należy zbindować jego źródło z właściwością AsyncItemsSource znajdującą się na DataGridzie. Źródło musi być obiektem klasy AsyncDataGridCollection<T>, gdzie T to typ danych, jaki będzie prezentowany w pojedynczym wierszu. Logika odpowiedzialna za pozyskiwanie danych powinna zostać zdefiniowana w pierwszym parametrze konstruktora klasy AsyncDataGridCollection. Pobrane dane natomiast powinny zostać przypisane do kolekcji Data.

Przykład.

Documents = new AsyncDataGridCollection<TradeDocumentListRow>(
    (token, o) =>
    {                   
                   //pobieranie danych
        var documents = GetDocumentsAsync(token, o);
 
                  //tylko jeden wątek może w danym momencie modyfikować kolekcję
        lock (Documents.DataLock)
        {
                           //obsługa anulowania pobierania
            if (token.IsCancellationRequested)
            return null;

                            //każde odświeżenie listy wymaga jej wyczyszczenia
            Documents.Data.Clear();
 				
                            //dodanie danych do kolekcji, którą odczyta DataGrid		 
            Documents.Data.AddRange(data);			
        }
 
    return documents;
    }, OnReceiptsOperationCompleted, loggingService);

 

Powyższy przykład przedstawia definicję właściwości Documents zaimplementowaną w konstruktorze view-modelu, która jest zbindowana z właściwością AsyncItemsSource kontrolki DataGrid. Pierwszy argument konstruktora to prosta logika pobierania danych (bez uwzględnienia stronicowania). Metoda zostanie automatycznie wywołana asynchronicznie bezpośrednio przez kontrolkę DataGrida, gdy tylko zostanie ona zainicjowana. Aby ręcznie zdecydować o momencie pobrania danych należy zmienić wartość właściwości LoadDataOnDataGridInitialization=false na obiekcie Documents. W momencie podjęcia decyzji o pobraniu danych wywołać metodę Documents.Refresh(false). Drugi argument konstruktora to metoda, która zostanie wywołana w wątku głównym (UI) tuż po zakończeniu logiki pobierania. Trzeci parametr to instancja serwisu do logowania błędów ILoggingService, dzięki której potencjalne wyjątki jakie zostaną rzucone w wątku pobierania zostaną zapisane w logu aplikacji.

Sortowanie danych

Stronicowanie może być zdefiniowane domyślnie oraz zmieniane przez użytkownika w dowolnym momencie poprzez kliknięcie na wybranej kolumnie. Domyślność z kolei można zmieniać w panelu zarządzania widokiem. Kontrolka sama nie realizuje zadania tyko zleca go źródle danych, inicjując metodę pobierająca dane przesyłając tylko informację o żądanym sposobie sortowania. Informacje w jakiś sposób posortować pobierane dane można odczytać z właściwości Sorting znajdującej się w obiekcie Documents.

Sorting : List<GridSortDescription> – lista zawierająca informację po której kolumnie sortowanie i w jaki sposób.

Składowe klasy GridSortDescription:

PropertyName : string – nazwa kolumny zdefiniowana we właściwości SortMemberPath kolumny. Jeżeli nazwa nie będzie zdefiniowana, domyślnie zostanie ustawiana taka jak nazwa właściwości użytej w bindingu.

Direction : ListSortDirection – kierunek sortowania, do wyboru rosnąco lub malejąco.

Column : DataGridColumn – referencja do kolumny

Stronicowanie listy

Stronicowanie, a w zasadzie doczytywanie dynamiczne danych podczas przewijania listy polega na tym, że kontrolka DataGrid w momencie gdy użytkownik zbliża się do końca listy inicjuje asynchroniczną metodę pobierająca dane informując źródło, że będzie potrzebną kolejną porcja jeżeli istnieje. Mechanizm ten pozwala na sprawną obsługuję dużych zbiorów danych, gdzie pobieranie całego zbioru nie byłoby efektywne i wydajne.

Sama logika stronicowa mysi być zaimplementowana w źródle. Aby wiedzieć, którą porcję danych żąda kontrolka należy skorzystać z właściwości ItemsToTake oraz ItemsToSkip znajdujących się w obiekcie klasy AsyncDataGridCollection<T>.

ItemsToTake : int – liczba wierszy danych, które żąda kontrolka.

ItemsToSkip : int – liczba wierszy danych, które należy pominąć licząc od początku zbioru (ta liczba reprezentuje liczbę wierszy, które zostały już pobrane wcześniej).

Grupowanie i agregacja

Kontrolka DataGrid wspiera mechanizm grupowania i agregacji wartości encji kolekcji prezentowanej przez kontrolkę. Włączenie funkcji grupowania wyłącza działanie mechanizmu stronicowania danych. Aby włączyć grupowanie, na kontrolce należy ustawić właściwość IsGroupingEnabled=”True”. Grupowanie jest w pełni zarządzalne w widoku zarządzaniu UI i pozwala na grupowanie i agregację po wcześniej zdefiniowanych właściwościach. Aby dana właściwość poddawała się grupowaniu należy oznaczyć ją atrybutem [AllowGroupBy] (z przestrzeni nazw: Comarch.POS.Core). Atrybut opcjonalnie pozwala na zdefiniowanie ścieżki do pliku resource oraz postfixu klucza z tłumaczeniem. Domyślnie jest to Properties.Resources, a każdy klucz to nazwa właściwości plus postfix Header. Na przykład dla właściwości o nazwie Name będzie to NameHeader.

Agregacja możliwa jest również tylko po wszystkich właściwościach oznaczonych atrybutem AllowGroupBy. W standardzie możliwe są następujące sposoby agregacji: Suma, Średnia, Maksimum, Minimum. Sposoby te działają tylko na właściwościach typu liczbowego lub string, który konwertuje się do typu liczbowego.

Rozszerzalność agregacji

W celu dodania własnego sposobu agregacji należy stworzyć nową klasę implementującą IAggregationType (przestrzeń nazw: Comarch.WPF.Controls.Aggregation). W klasie tej należy zaimplementować mechanizm agregacji  we właściwości Function.

Jeżeli zakładamy, że nasza nowa agregacja będzie realizowana tylko na liczbach możemy podziedziczyć po klasie AggregationNumberType zamiast implementować interfejs. Następnie przeciążyć metodę Aggregate bez potrzeby przejmowania się weryfikacją typów agregowanych danych.

Na koniec stworzoną klasę należy zarejestrować jako nowy sposób agregacji w systemie. W klasie Module należy wywołać metodę RegisterDataGridGroupAggregation, przekazać nazwę klasy oraz zdefiniować klucz i resource, z którego zostanie pobrane tłumaczenia dla nowego sposobu agregacji.

Więcej szczegółów w Przykład implementacji własnego sposobu agregacji danych w DataGridzie

Grupowanie po atrybutach

Grupowanie i agregacja po atrybutach działa automatycznie i nie wymaga dodatkowej implementacji. Ważne tylko, aby obiekt elementu zawierający atrybuty posiadał właściwości:

  • Attributes typu słownikowego Dictionary<string,AttributeEntity>
  • AttributeRows typu AttributesDictionary

Czy ten artykuł był pomocny?