ListView – kontrolka dostępna od SDK 2.0 w przestrzeni nazw Osp::Ui::Controls, która wyświetla opcje wyboru w postaci listy.
Elementy listy dzielą się na dwa rodzaje:
- SimpleItem – proste opcje listy ze stałym szablonem (Layout) z możliwością dodania ikonki i tekstu przez użytkownika.
- CustomItem – w pełni konfigurowalna przez użytkownika opcja listy.
Korzystanie z ListView wymaga zaimplementowania pewnych metod z interfejsu Osp::Ui::Controls::IListViewItemProvider:
virtual Osp::Ui::Controls::ListItemBase* CreateItem(int index, int itemWidth); virtual bool DeleteItem(int index, Osp::Ui::Controls::ListItemBase *pItem, int itemWidth); virtual int GetItemCount(void);
CreateItem() – Metoda odpowiedzialna za tworzenie elementu listy.
DeleteItem() – Metoda odpowiedzialna za zwalnianie zasobów po usunięciu elementu z listy.
GetItemCount() – Metoda odpowiedzialna za zwracanie ilości elementów w liście.
W większości przypadków, powyższe metody powinny być implementowane przez klasę formularza, na którym znajduje się kontrolka ListView, ale może to być dowolna inna klasa, która posiada implementację interfejsu Osp::Ui::Controls::IListViewItemProvider. Wybór jak zawsze zależy przede wszystkim od programisty.
Wierzę, że masz już stworzony pusty projekt 🙂 Więc zaczynamy.
Na formularzu umieszczamy kontrolkę ListView, którą znajdziemy w oknie ToolBox.
Jeśli chcesz żeby kontrolka ListView zajmowała cały obszar formularza, postępuj zgodnie z poniższymi wskazówkami.
Zaznacz kontrolkę na formularzu i w oknie Properties zmień następujące atrybuty:
Od teraz nasza kontrolka będzie zajmowała obszar całego formularza i zostanie wyrównana do lewej górnej krawędzi formularza.
W tej chwili lista jest pusta i wyświetlany jest komunikat „Blank”. Jeśli chcesz go zmienić, wystarczy zmodyfikować atrybut Text Of Empty List i podać np. „Brak danych”.
Zanim zaimplementujemy metody z opisywanego wcześniej interfejsu, powinniśmy mieć czym wypełnić naszą listę. Nasz przykładowy program będzie po prostu pobierał teksty z kolekcji, którą za chwilę stworzymy.
W pliku nagłówkowym (.h) formularza w sekcji protected deklarujemy naszą kolekcję:
protected: Osp::Base::Collection::ArrayListT<Osp::Base::String*> __strings;
Następnie w pliku źródłowym formularza (.cpp) inicjalizujemy kolekcję przykładowymi danymi:
result Form1::OnInitializing(void) { result r = E_SUCCESS; __strings.Construct(); __strings.Add(new String(L"Opcja 1")); __strings.Add(new String(L"Opcja 2")); __strings.Add(new String(L"Opcja 3")); __strings.Add(new String(L"Opcja 4")); __strings.Add(new String(L"Opcja 5")); return r; }
Pozostały nam już tylko trzy metody interfejsu IListViewItemProvider do zaimplementowania.
Zaznaczamy naszą kontrolkę ListView na formularzu i w oknie Properties odnajdujemy widoczny atrybut. Zaznaczamy go i klikamy przycisk Add.
W tym momencie nasz plik nagłówkowy wzbogacił się o dziedziczenie po interfejsie, a plik źródłowy o trzy puste metody opisane na początku (na zielono). Przy okazji została zmodyfikowana funkcja OnInitializing() o definicje dostawcy danych (Provider) – linia 12-16:
result Form1::OnInitializing(void) { result r = E_SUCCESS; __strings.Construct(); __strings.Add(new String(L"Opcja 1")); __strings.Add(new String(L"Opcja 2")); __strings.Add(new String(L"Opcja 3")); __strings.Add(new String(L"Opcja 4")); __strings.Add(new String(L"Opcja 5")); ListView *pListview1 = static_cast<ListView *>(GetControl("IDC_LISTVIEW1")); if (pListview1) { pListview1->SetItemProvider(*this); } return r; }
Oto nasza implementacja metod po oprogramowaniu:
/* * Funkcja tworząca opcję w ListView * Wykonuje się tyle razy, ile wynosi liczba elementów w kolekcji * @see GetItemCount() */ Osp::Ui::Controls::ListItemBase* Form1::CreateItem (int index, int itemWidth) { ListAnnexStyle style = LIST_ANNEX_STYLE_NORMAL; SimpleItem* item = new SimpleItem(); item->Construct(Osp::Graphics::Dimension(itemWidth, 75), style); String* text; __strings.GetAt(index, text); item->SetElement(*text, null); return item; } /** * Zwalnia zasoby * Zwracamy True - jeśli zwalniamy w tej metodzie, False - jeśli ma to zrobić ListView */ bool Form1::DeleteItem(int index, Osp::Ui::Controls::ListItemBase *pItem, int itemWidth) { return false; } /** * Zwraca liczbę elementów kolekcji */ int Form1::GetItemCount(void) { return __strings.GetCount(); }
Nasz program po uruchomieniu wygląda tak:
Za styl opcji odpowiedzialna jest zmienna style z metody CreateItem(). Może ona posiadać następujące wartości:
LIST_ANNEX_STYLE_NORMAL – bez stylu
LIST_ANNEX_STYLE_MARK – opcja z zaznaczeniem checkbox
LIST_ANNEX_STYLE_ONOFF_SLIDING – opcja z przełącznikiem typu On/Off
LIST_ANNEX_STYLE_DETAILED – Opcja ze strzałeczką w sensie „czytaj dalej”
LIST_ANNEX_STYLE_RADIO – opcja z przyciskiem typu radio
Poniżej przykład z opcjami o rożnych stylach:
To co nam pozostało to zwolnić zasoby – naszą kolekcję.
result Form1::OnTerminating(void) { result r = E_SUCCESS; Osp::Base::Collection::IEnumeratorT<String*>* pEnum = __strings.GetEnumeratorN(); while (pEnum->MoveNext() == E_SUCCESS) { String* temp; pEnum->GetCurrent(temp); delete temp; temp = null; } __strings.RemoveAll(); return r; }
Jeśli zawartość kolekcji uległa zmianie, np. zostały dodane lub usunięte dane, listę należy odświeżyć w następujący sposób:
ListView *pListview1 = static_cast(GetControl("IDC_LISTVIEW1")); if (pListview1) pListview1->UpdateList(); pListview1->RequestRedraw(); }
Żeby za każdym razem nie pobierać wskaźnika do ListView, należy zrobić to tylko raz w funkcji OnInitializing() przypisując adres listy do zmiennej z widocznością protected lub private, zamiast do zmiennej lokalnej – jak to jest w tej chwili.
Pobierz projekt: ListViewSimpleExample.zip
ListView może posiadać także ikonkę.
Ikonkę należy podać jako drugi parametr funkcji:
SetElement(const Osp::Base::String &text, const Osp::Graphics::Bitmap *pBitmap=null)
Dziś zrobię ewentualnie drobną modyfikację artykułu, żeby w miarę pełnie opisać możliwości klasy SimpleItem.
Świetny artykulik, prosty i przejrzysty. Akurat potrzebowałem czegoś takiego 🙂