Přidání obsahu do buňky v DataGridView

Uběhlo již mnoho času od chvíle, kdy jsem se naposledy věnoval některému z příspěvků na fóru o .net na serveru builder.cz. Nyní se však na tomto fóru objevilo několik začátečníků, kteří se nespokojí jen s ukázáním cesty, ale rádi by viděli i kus kódu, který jim vydláždí cestu k vytouženému cíly.

Jeden z požadavků uveřejníl i přispěvatel lopy123, který by rád věděl, jak je možné přidat obsah do buňky v DataGridView. Celou otázku a diskuzi je možné sledovat ve zmíněném vlákně. Já jsem otázku dlouhou dobu registroval, ale blíže jsem se jí nevěnoval a to hned z několika důvodů.

Jedním z oněch důvodů byl již požadavek samotný, kdy mi přišlo chování poněkud netypické a nestandardní. V případě, kdy požaduji vložit, resp. přidat text k již existujícímu textu, nejdříve vstoupím do buňky a až následně si vyberu místo, kam text vložím.

Přejdu však k řešení, ke kterému jsem se nakonec odhodlal. Možná proto, že odpovědi, které jsem si postupně četl se přesunuly až k použití win API funkcí a to bylo v takovém případě celkem zbytečné.

Jednoduchý kód řešící problém

Výsledný kód řešící daný problém je vcelku jednoduchý. Je třeba se jen maličko zamyslet nad tím, co se vlastně v datagridview "děje", když uživatel chce editovat text uvnitř buňky.

Nejdříve si tedy registrujeme odběr události, ke které dochází při zobrazení editovacího prvku, konkrétně tedy EditingControlShowing. To můžeme udělat v okně Properties daného DataGridView, kdy se nám vygeneruje do obslužného kódu aplikace šablona metody. Do této šablony pak doplníme obsluhu události.

private void gridLopy_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) {
    TextBox txt = e.Control as TextBox;
    if (txt != null) {
        txt.KeyPress -= txt_KeyPress;
        txt.KeyPress += txt_KeyPress;
    }
}

Jediné, co v obsluze provádím je, že zjišťuji, zda editovacím prvkem je TextBox - pro ostatní prvky to nemá příliš význam (samozřejmě, pokud nebudeme implementovat nějaký vlastní textový editor). Poté, nejen pro jistotu, odregistrujeme událost stisku klávesy KeyPress a následně si zaregistrujeme její odběr.

Proč dochází nejdříve k odregistrování odběru události? Odpověď je opět velice jednoduchá. DataGridView používá vždy pouze jednu instanci editovacího prvku pro daný typ. Tudíž, pokud by nedošlo nejdříve k odregistraci události, tyto by se postupně vršili a docházelo by k jejich několikanásobnému vyvolávání, což je v tomto případě nežádoucí.

Poté je již dostačující vhodně ošetřit přidání znaku na potřebné místo. Samozřejmě by bylo možné implementovat lepší algoritmus, ale pro "nástřel" možného řešení jsem zvolil přidání znaků nebo číslic na konec textu.

void txt_KeyPress(object sender, KeyPressEventArgs e) {
    TextBox txt = sender as TextBox;
    if (txt != null) {
        if (char.IsLetterOrDigit(e.KeyChar)) {
            txt.Text = txt.Text + e.KeyChar;
            txt.SelectionStart = txt.Text.Length ;
            e.Handled = true;
        }
    }
}

Jak je vidět, výsledný kód není skutečně složitý. Co je však důležité, pochopit princip práce DataGridView. Snad to přispěvateli lopy123 a nejen jemu pomůže.

6 Comments

  • lopy123 said

    fajne hezkém, jednoduché, chytré - ale na tu ono cestu, která mě má přivést k "cíli" mě lidé, kteří se mi svémy názory snažil pomoct svedli. Dělal jsem to úplně jinak a o události EditingControlShowing nepadlo slovo.

  • lopy123 said

    Ještě jsem se chtěl zeptat prosim tě jestli by si mohl rozvést to odregistrovaní údalosti a pak následné zaragistrování...
    "DataGridView používá vždy pouze jednu instanci editovacího prvku pro daný typ." nebo přejsněji, tato věta není jasná. díky

  • Jarda Jirava said

    Ahoj, k těm doplňujícím otázkám. Jedná se o to, že DataGridView používá vždy jen jednu instanci daného editovacího prvku pro všechny editaci. Jako příklad použiji onen zmiňovaný TextBox. DataGridView vytvoří jen jednu instanci a tu použije všude tam, kde má dojít k editaci pomocí TextBoxu. Proto je nutné nejdříve odregistrovat událost a následně ji zaregistrovat (pro první použití), nebo využít jinou techniku (např. proměnnou na úrovni třídy). Toto mi však přišlo jako nejsnazší řešení. btw. byl nějaký důvod, proč jste nevyplnili kontakt na sebe? Díky

  • lopy123 said

    ani newim. web nemám a mail používám jen pro RSS, různé registrování na na webech a při výjímečných situacích.

  • Ondra Medek` said

    Ja bych rekl, ze ve skutecnosti tu jedinnou instanci editujiciho prvku pouziva prave pouze pro textbox. Kdyz se udela sloupec s checkboxy, buttony nebo s necim jinym, tak tam bude asi pro kazdou bunku jeden prvek.

Add a Comment