Jarda Jirava

Vývojář a architekt řešení postavených na technologii .net framework. Zabývám se jak vývojem webových aplikací za pomoci asp.net, tak také desktopových aplikací winform. Při návrhu řešení a samotném vývoji pak využívám dlouholetých zkušeností se zpracováním obchodní logiky a pravidel aplikací získaných z vývoje komerčních aplikací pro finanční a bankovní instituce.

Microsoft MVP

Microsoft MVP - Client App dev

Silverlight minesweeper

Get Microsoft Silverlight

Navrhi COOL design a vyhraj zkušební let po Evropě!

Poslední příspěvky

.net technology

1
I

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.

Publikováno pod: .net technology , builder.cz
4
XI

II. neformální setkání .net builder.cz

Ve čtvrtek se konalo již druhé neformální setkání přispěvatelů konference .net na serveru builder.cz, které se mi podařilo uspořádat. Oproti prvotnímu setkání jsme se tentokrát setkali v celkovém počtu 9 vývojářů a to na známém místě v prostředí restaurace Studna.

Probírala se nejrůznější témata, která mohou vývojáře při jeho profesní činnosti potkat. Co si dobře pamatuji, tak jedno z provotních témat byl vesmírný výtah, jeho konstrukce, možnosti a realizovatelnost.

Poté, co jsme se sešli ve větším počtu - ne každý byl dochvilný - proběhlo krátké představení každého účastníka setkání. Tím jsme se dostali k porovnání toho, jaký je rozdíl mezi kodérem a vývojářem.

Dále už následovalo jedno téma za druhým, většinou pak na některé z .net témat, asi nejvíce aktivní byl pak Jakub Müller.

Konec celého setkání se rychle přiblížil avšak ještě dříve než skončil, stačil dorazit i Jirka Zídek.

Jak a kdy příště

Příští setkání bych rád uskutečnil ještě v malinko větším počtu účastníků a také nejspíše v jiné restauraci, tak aby bylo možné si posedat dle zájmu každého účastníka a pohovořit si s každým. Alespoň dle ohlasů některých účastníků, by se další mohlo konat již brzy a to někdy na přelomu ledna a února příštího roku.

Na samotný závěr mi dovolte se ještě jednou omluvit, neboť jsem byl malinko zdravotně indisponován a tolik jsem se nezapojil do všech debat. Zrada byla v nové klimatizaci a hlavně pak mém hlase.

Publikováno pod: .net technology
3
X

Vývojáři, řekněte WoW!

Na tuhle chvíli určitě čekal kdekterý vývojář. Každý z nás si pomáhal jak mohl, a nejčastějším pomocníkem v našich otázkách a hledání odpovědí při řešení našich úkolů, pak byl reflector for .net.

Ten však již bzry nebude třeba, alespoň ne tedy pro assembly z .net frameworku 3.5. Scott Guthrie dnes na svém blogu přinesl velice potěšující zprávu. 

Zdrojové kódy pro .net framework 3.5 budou k dispozici a to již velice brzy. Navíc bude možné ladit skrz zdrojový kód těchto assemblies a to z prostředí nového VS 2008. Tak teď si konečně můžeme i my vývojáři říci WoW!

Publikováno pod: .net technology
13
VIII

ASP.NET Page pro začátečníky

Poměrně často přicházím do kontaktu se začátečníky, kteří se chtějí naučit pracovat s technologií .net. Jejich volba pak většinou míří na web a tedy použítí a tvorbu asp.net stránek.

Před takovými začátečníky však stojí poměrně velký znalostní kopec, který musí překonat, než pochopí, jak takovou stránku správně ovládat. Jelikož má asp.net stránka - třída Page - poměrně bohatý událostní model, není vždy úplně jasné a na první pohled zřejmé, co v kterou chvíli dělat a kam vlastně soustředit veškeré své úsilí.

Přestože jsem byl v prvních rocích též nadšen, obdobně jako třeba Michal Valášek - vzpomínám ještě na jeho první prezentaci o asp.net - s příchodem asp.net 2.0 toto mé nadšení malinko opadlo a já se začal dívat i na jiné možnosti. (To, jakou možnost jsem nakonec zvolil, nechám ještě chvilku v utajení, abyste si mohli zasoutěžit.)

A třeba i tento týden, kdy jsem napsal článek o tom, kdy získat a navázat data na zobrazovací prvky, mě jen utvrdil v tom, že pro začátečníky by to chtělo něco trošku jednoduššího.

ASP.NET beginner page

A tak mě napadlo, jak by tak mohla vypadat, alespoň co se týká událostního modelu taková beginner page, stránka určená pro začátečníky, nebo i pro ty, kteří nepotřebují využít všech nabízených událostí - a že se to zas tak často děje.

Co by taková třída měla umožnit. Stále je založena na implementaci page controlleru, stejně jako současná Page, avšak má jen potřebné události, které je nutné obsloužit a zároveň je malinko, logičtěji, uspořádává. Tím by mělo být zároveň zajištěno, že by nepřipustila, aby docházelo k poměrně častým, školáckým, chybám.

Posloupnost obsluhovaných událostí

  • Init - v této události má vývojář možnost ovlivnit / zrekonstruovat objektový model stránky ještě před tím, než budou dotažena data ze zaslaného requestu. Toto obnovení by v případě úplných začátečníků mohlo být nahrazeno uložením objektového stromu do ViewState. Pro vyvolání událostí pak použít AutoEventWireup a začátečníka událostí nezatěžovat.
  • Change a Command - zpracování reakcí na klientovo chování - interakci s aplikací. Jak už jsem se zmínil v předchozím článku, Obsluhu události Load můžeme vynechat, neboť data můžeme získat i později a s menší pravděpodobností výskytu chyby.
  • DataRetrieve - po zpracování reakcí od klienta je možné na jejich základě získat data a navázat je na zobrazovací prvky

Pro začátečníka myslím plně dostačující událostní model. Samozřejmě stále by měl možnost reagovat na události zobrazovacích prvků jako třeba GridView a jeho RowDataBound, které nesouvisí s událostmi stránky.

Teorie krásná věc

To co jsem výše popsal je jen moje teorie, která vznikla jako reakce na události uplynulých dnů a z otázek asp.net začátečníků. Jak ji však přenést do praxe? Je mi celkem jasné, že asi nepůjde jenom podědit třídu Page a skrýt události, ale bude to chtít vytvořit vlastní implementaci asp.net Page controlleru a zároveň zachovat veškerou funkcionalitu, která je v současné chvíli.

Takto popsané to vypadá velice jednoduše, ale co na takový první pohled takto vypadá, většinou se změní ve složitý oříšek, a pokud by se našel dobrovolník, který by chtěl pomoci, určitě se nebudu zlobit, když se zapojí a bude alespoň konzultantem. Zatím mám v hlavě nápad a chuť jej realizovat, teď ještě najít dostatek času a pustit se do toho.

Myslíte, že to má vůbec význam, se do toho pouštět a nebo vidíte nějaký neřešitelný zádrhel?

Publikováno pod: .net technology
6
VIII

ASP.NET vázání dat na zobrazovací prvky

Kdy správně získat data z datového zdroje a data nabindovat na zobrazovací ovládací prvky, to bylo tématem dnešního rozhovoru a já slíbil, že zkusím obhájit své stanovisko.

Zapředl jsem se totiž do rozhovoru s Martinem a to na základě otázky a jeho odpovědí z tohoto příspěvku. Tazatel se ptal, zda existuje funkce na obnovení dat v GridView a přispěvatel se jménem studentik mu odpověděl, nechť použije událost PreRender. Martin poté upozornil, že tato událost není tím správným místem, kde provést dotaz do datového zdroje a nabindovat data. Odkázal přitom na stránku věnovanou tomuto tématu ASP.NET Page life cycle overview, kde jsou popsány jednotlivé události stránky Page.

Já vycházel z mého již dříve napsaného článku o životním cyklu stránky a zkušeností, které mám s tvorbou asp.net aplikací a nemohl jsem s Martinem souhlasit.

Kdy tedy provést navázání dat?

Nemohu souhlasit s tvrzením, že vázat data na zobrazovací prvky by se mělo již v události Init událostního modelu stránky. V tomto kroku jsou inicializovány jednotlivé prvky a rekonstruuje se objektový model stránky. Samozřejmě, pokud nemáme k dispozici ViewState je to pravé místo, pro to jej "nahradit" a získat tak obraz zobrazovaných dat, tak aby se mohli vytvořit všechny potřebné zobrazovací prvky i s jejich, na klienta, odesílanými údaji.

Posléze, v následujícím zpracování životního cyklu stránky, dojde k načtení dat z ViewState - v případě jeho vypnutí simulujeme napojením dat - a následně k nastavení hodnot formulářových prvků hodnotami z předané kolekce Forms.

Život stránky jde dál a následuje událost Load stránky, kdy se většinou provádí test na vlastnost IsPostBack a případné nahrání a navázání dat. Začátečnickou chybou tak je, že nedojde k otestování zda došlo k postbacku a tak si vývojář přepíše získaná data jejich původní hodnotou a nadělá si spoustu problémů, které neví jak řešit. I proto se mi jeví navázání dat v tomto okamžiku jako nevhodné a vlastně se tím nic nezíská.

A to i vzhledem k tomu, že následuje vyvolání a zpracování změnových např. textchanged a postback událostí - pro prvky implementujících rozhraní IPostBackEventHandler. Kde se snažíme o uložení dat zaslaných klientem do naší aplikace a zároveň můžeme na základě jeho rozhodnutí provádět další operace s naší aplikací. Tyto operace pak mohou vést k tomu, že zdroj dat bude jiný nebo bude obsahovat jiné hodnoty, které v okamžiku zpracování předchozích události ještě nevíme - nebyli jsme o nich informováni, samozřejmě si je můžeme zjistit již dříve, například přímým dotazem na hodnotu do kolekce Forms.

Získání dat a jejich navázání

A právě po proběhnutí výše uvedených akcí je myslím nejvhodnější doba, kdy získat nová data a provést jejich navázání na zobrazovací prvky. Pro verze asp.net 1.x je tedy možné využít události PreRender,pro asp.net 2.0, kde byl událostní model rozšířen, je to událost LoadComplete - samozřejmě je též možné využít PreRender událost.

Určitě se ptáte, jaké k tomu mám podklady, že doporučuji zrovna tyto události. Na prvním místě jsou to osobní zkušenosti, které jen těžko něco může nahradit. Již zmíněné chování, kdy dochází k postupnému "uvědomování si" co vlastně uživatel chce zobrazit až třeba po implementaci asynchronního volání ve verzi asp.net 2.0. Kde je možné si zaregistrovat počáteční a koncový handler v metodě AddOnPreRenderCompleteAsync a kdy ke zpracování asynchronního volání dojde v okamžiku mezi voláním metod OnPreRender a OnPreRenderComplete - tedy taktéž je využito tohoto okamžiku, abychom výsledek zdlouhavé operace navázali na zobrazovací prvek ve stránce.

Samozřejmě budu rád, pokud se mnou nebudete souhlasit a opravíte mě, já se alespoň poučím. Uvítám však i opačný názor, že nejsem sám, kdo k tomuto řešení dospěl.

Publikováno pod: .net technology , builder.cz
3
VIII

.net aplikace proti mysql databazi

Dostal jsem se k možnosti vytvořit jednoduchou aplikaci, která se bude starat o import dat do mysql databáze. Říkal jsem si, že by to neměl být velký problém, podobných můstků jsem již několik vytvořil a tak jsem se do toho pustil.

Jelikož jsem měl již dřívější zkušenosti s mysql tak mi bylo jasné, že cesta přes ODBC určitě nepovede, protože je ve verzi 3.51 stále ještě chyba při ukládání datových typů (a možná to není jediná chyba) a vyšší verzi jsem nenašel.

Na stránkách mysql je k dispozici connector pro připojení k mysql databázi a tak jsem jej hodlal vyzkoušet. Aplikace pro import byla napsána poměrně rychle, a tak nastal čas testování.

Připojení a dotazy do mysql

A právě fáze testování přinesla, pro účely aplikace, nelichotivé výsledky. Aktualizace probíhala pomocí volání metody ExecuteNonQuery() na vytvořené instanci třídy MySqlCommand s naplněnými parametry. Čas potřebný k vykonání jednoho dotazu, sestávajícího pouze z volání dané metody, byl v rozmezí 60-80ms. Což představovalo v podání profileru nějakých 98% celkového času práce aplikace. Po vynásobení množstvím záznamů jsem se dostal k neúnosným číslům.

Alternativy v připojení nebo změna aplikace?

Začal jsem tedy hledat alternativy v připojení k mysql databázi. Vyzkoušel jsem ještě jeden provider, který měl však velice podobné časové nároky a tak nezbývalo, než zkusit změnit chování samotné aplikace. První varianta, která mě napadla je, celé to přesunout do samostatných vláken, což jsem ale záhy zamítl. Nechtěl jsem začít spravovat jednotlivá vlákna a ani ThreadPool jsem v tomto scénáři nechtěl použít - spíše šlo o jistou intuici a třeba jsem to měl zkusit.

Obdobně dopadl, tentokát již vyzkoušený pokus s voláním asynchronních metod, které jsou ve verzi ADO.NET 2.0 podporovány. I tak však vykonání několika stovek až tisíců příkazů bylo časově neúnosné. A tak jsem zkusil poslední možnost, která mě napadla.

Naplnil jsem vstupnímy daty DataTable a tu jsem pomocí vytvořeného DataAdapteru naimportoval do databáze. Výkon sice nebyl oslňující, ale přeci jen citelně lepší než v předchozích dvou případech. Navíc se v tomto scénáři dalo velice dobře využít výhod ThreadPoolu a to pro každou importovanou DataTable.

Víte o něčem lepším?

Je klidně možné, že existuje ještě lepší řešení, nebo i rychlejší connector pro přístup k mysql databázi. Pokud se chcete podělit, vaše rady určitě přivítám.

Publikováno pod: .net technology