RSS Feed

Edytowalny ListBox

Dużo czasu spędzam ostatnio przy mini projekcicku [więcej info wkrótce]. Potrzebowałem kontrolki listboxa ale z edytowalnymi polami.
Jako że w .necie taka kontrolka nie jest dostępna standardowo to postanowiłem “wyciosać” własną. .Net daje nam spore pole do popisu jeżeli chodzi o tworzenie własnych “customowych” kontrolek.

By tego dokonać będziemy potrzebować dwóch nowych kontrolek.

  • TextBoxa  który będzie komunikował się z danymi ListBoxa
  • ListBoxa wykorzystującego tego TextBoxa

Opis Działania.

ListBox normalnie wyświetli Itemy. W momencie wybrania któregoś pola w miejscu Itema wygeneruje odpowiednią kontrolkę TextBoxa. Po wprowadzeniu textu do TextBoxa będzie on znikał i tracił “focus” przesyłając zmiany do ListBoxa , [ skupienie 😀 jak to dziwnie brzmi ostatnio zauważyłem że niektóre wydawnictwa tłumaczą “singleton” jako “samotnik” ].

TextBox

Zaczniemy od TextBoxa bo zawiera on mniej modyfikacji.

    class EdditableTextBox : TextBox
    {
        private int _index = -1;

        public int Index
        {
            set { _index = value; }
        }

Dziedziczymy po standardowum TextBoxie i definiujemy pole Index , które będzie zawierać numer naszego obiektu , itemu , w listBoxie.

        protected override void OnLeave(EventArgs e)
        {

            ((ListBox)this.Parent).Items[_index] = this.Text;
            base.OnLeave(e);
        }

Przeciążamy metodę wywoływaną w momencie wychodzenia z textBoxa tak by wszelkie wprowadzone zmiany zmieniały także obiekt w naszym ListBoxie do tego jest nam potrzebny parametr Index , który określa do którego konkretnie elementu się odnosimy.Odwołanie do ListBoxa realizujemy poprzez propercje Parent.

Na wszelki wypadek wywołujemy bazową metodę.

Można oczywiście zrobić inny mechanizm. Np akceptowanie zmian w momencie wciśnięcia odpowiegniego klawisza.

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                ((ListBox)this.Parent).Items[_index] = this.Text;
            }
            base.OnKeyPress(e);
        }

W tym przypadku Enter

ListBox

Przejdzmy teraz do ListBoxa. Tutaj już będzie troszeczkę więcej zmian.

class EdditableListBox : ListBox
    {
        private static int MarginBeetwenItems = 5;
        private EdditableTextBox tbox;

Dziedziczymy po ListBoxie tworzymy propercje oznaczającą odstęp pomiędzy wyświetlanymi itemamy i tworzymy lokalna kopię naszego zmodyfikowanego TextBoxa

	public EdditableListBox()
        {
            tbox = new EdditableTextBox();
            tbox.Hide();
            tbox.Parent = this;
            Controls.Add(tbox);
        }
	

Tworzymy Text Boxa ustawiamy jego “rodzica” . Propercja Parent będzie nam służyła do komunikacji pomiędzy TextBoxem i ListBoxem.

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index > -1)
            {
                string s = Items[e.Index].ToString();

                Rectangle rect = new Rectangle(
                    e.Bounds.X, e.Bounds.Y + (e.Index * MarginBeetwenItems),
                    e.Bounds.Width, e.Bounds.Height);

                e.Graphics.DrawString(s, Font, new SolidBrush(SystemColors.WindowText), rect);
            }
        }
			

Musimy przeciążyć metodę odrysowywującą. Na wszelki wypadek badamy index Obiektu w ListBoxie , wyznaczamy prostokąt na podstawie jego parametrów , uwzględniając
MarginBeetwenItems. Rysujemy napis w odpowiednim miejscu.


	 protected override void OnMouseUp(MouseEventArgs e)
        {
            int index = IndexFromPoint(e.X, e.Y);

            if (index != ListBox.NoMatches && index != 65535)
            {
                if (e.Button == MouseButtons.Left)
                {
                    string s = Items[index].ToString();
                    Rectangle rect = GetItemRectangle(index);

                    tbox.Location = new Point(rect.X, rect.Y + (index * MarginBeetwenItems));
                    tbox.Size = new Size(rect.Width, rect.Height);
                    tbox.Text = s;
                    tbox.Index = index;
                    tbox.SelectAll();
                    tbox.Show();
                    tbox.Focus();
                }
            }

            base.OnMouseUp(e);
        }

Główna metoda tworząca [chociaż bardziej pasuje słowo modyfikująca] odpowiednio kontrolke TextBoxa , przy kliknięciu Lewym Przyciskiem myszki. Parametry TextBoxa modyfikujemy tak aby wyświetlał się w miejscu klikniętego obiektu na ListBoxie.


	protected override void OnSelectedIndexChanged(EventArgs e)
        {
            tbox.Hide();
            base.OnSelectedIndexChanged(e);
        }

        protected override void OnLeave(EventArgs e)
        {
            tbox.Hide();
            base.OnLeave(e);
        }
		

Odpowiednie funkcje powodujące zniknięcie naszego TextBoxa przy wyjściu z kontrolki i przy zmianie obiektu.

Advertisements


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s