Skip to main content

UI: Simple ListView – Lista

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:

  1. SimpleItem – proste opcje listy ze stałym szablonem (Layout) z możliwością dodania ikonki i tekstu przez użytkownika.
  2. 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

markac

Full-stack Web Developer

3 thoughts to “UI: Simple ListView – Lista”

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

  2. Świetny artykulik, prosty i przejrzysty. Akurat potrzebowałem czegoś takiego 🙂

Komentarze są zamknięte.