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

Poslední příspěvky

21
Oct

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

Již po sedmé píši obdobný text výzvy k neformálnímu setkání .net vývojářů. Pojďme na chvíli opustit kanceláře a popovídat si s lidmi, kteří řeší obdobné úkoly a které známe jen podle nicku z online konference.

Předpokládám, že opět uvidím známé tváře, ale určitě se těším i na tváře nové.

Jestliže tedy máte chuť, náladu a čas nejen posedět, ale také popovídat, v některé z příjemných pražských restaurací, rád vás uvidím:

Kdy: 5. nebo 12. listopadu (čtvrtek – výběr dne je na vás)

V kolik: začátek je plánován na 18:30 (v té době dochází totiž k nejčastějším výpadkům serverů ;-))

Registrace: provedete odesláním komentáře pod tímto příspěvkem i s výběrem pro vás vyhovujícího datumu a nezapomeňte připojit i váš email.

Datum, který bude mít nejvíce vašich hlasů, bude určen za den setkání. V týdnu setkání se pak můžete těšit na emailovou připomínku a adresu vybrané restaurace.

Samozřejmě jsou vítání všichni, jak tváře známé, tak i zatím tváře neznámé – samozřejmě, že budete vítání i v případě, že nepříspíváte do konference, ale o .net se zajímáte.

Registrace je otevřena do 30.10.2009.

Publikováno pod: builder.cz , .net technology
19
Oct

DevDays 2009 s VS2010 Beta 2

Developer Days 2009 se blíží!

Jako již tradičně, i letos v listopadu proběhne vývojářská konference Developer Days. Očekávejte ovšem některé změny. Na základě podnětů z minulých ročníků jsou obsahem letošní konference čistě technická témata. Dále se můžete těšit na soutěž o nejlepší demo a též na MVP-ky (Microsoft Most Valued Professional), kteří vám v průběhu přestávek předvedou své oblíbené vychytávky a v sekci “Ask the Experts” pak rádi odpoví na vaše dotazy. Co naopak zůstává beze změny – bez ohledu na rozpočet zužovaný neradostnou ekonomickou situací – je cena vstupného. Ta zůstává na stejné úrovni jako vloni, tedy 0 Kč.

Letošní Developer Days pořádáme v Praze a Ostravě, registraci a další informace najdete na www.devdays.cz. Pražské Developer Days jsou již naplněné, ale v Ostravě je stále dostatek volných míst. Pokud to máte do Ostravy daleko, můžete během následujících měsíců navštívit některý z plánovaných seminářů, kde se o tom nejlepším z letošních Developer Days dozvíte. Detailní informace o konání seminářů najdete v listopadu na webu WUGu.
Komu vyhovuje zůstat u svého počítače, může se podívat na obsah konference online, po 28. 11. na www.devdays.cz.

Jak mnozí zjistili, tak právě dnes byla uvolněna Beta 2 verze nového Visual Studia 2010 pro MSDN předplatitele a pozítří si ji budou moci stáhnout a vyzkoušet i vývojáři, kteří předplatné ještě stále nemají. A právě VS2010 bude hlavní náplní Developer Days, máte se určitě na co těšit.

Určitě jedna důležitá informace, Beta 2 má tzv. go-live licenci.

Publikováno pod: .net technology
22
Sep

Sketchflow – Azure desktop v0.2

Pokračuji dle definovaného scénáře a publikoval jsem druhou verzi návrhu UI pro Azure desktop. Bohužel jsem nemohl zahrnout žádnou připomínku, neboť jsem žádný sketchflow feedback zatím neobdržel. Což se doufám tímto releasem změní :-).

Vzorová data

Co jsem však obdržel byl feedback jiný a to, že schází nejen zbylé komponenty, ale především vzorová data, která by práci s Azure desktopem objasnila. To jsem se snažil napravit a tak vznikla tato verze, která obsahuje kompletní UI a napojení na vzorová data.

Neboť je mi jasné, že ne všichni máte již svá data migrována na Azure data storage, třeba pomocí této utility, tak jsem si nechal vygenerovat vzorová data přímo aplikací Expression Blend. Sice jsem tím ztratil maličko na reálnosti pořízených dat, na druhou stranu jsem tak plně využil potenciálu, který návrh UI s Sketchflow tento nástroj nabízí.

Připomínky vítány

Jelikož bych rád zapracoval veškeré připomínky do finální verze co nejdříve, budu rád za zaslání připomínek do tohoto pátku, tedy 25.9.2009. Jakým způsobem vytvořit feedback se mi doufám povedlo srozumitelně popsat v minulém příspěvku, obdobně jako zamýšlený princip fungování Azure desktop aplikace.

Samozřejmě budu rád za inspirativní nápady.

Publikováno pod: .net technology , wpf
16
Sep

Sketchflow – Azure desktop

Jelikož se poměrně kvapem blíží uvedení Azure služeb do ostrého provozu, rozhodl jsem se vytvořit obslužný program, který umožní prohlížení a manipulaci s daty uloženými v tomto, nejen datovém úložišti, tzv. cloudu.

Vím o tom, že nejsem příliš zdatným grafikem a také designerem UI, přesto bych byl rád, kdyby tento desktopový program byl dobře použitelný a stal se praktickým pomocníkem každého, kdo si nechá svá data spravovat pomocí Azure datových služeb.

Expression Blend 3 a Sketchflow

Součástí produktu Expression Blend se od verze 3 stal nedílnou součástí také návrhář tzv. Sketchflow, který má umožnit navrhnout poměrně jednoduchou formou vizuální podobu jednotlivých obrazovek aplikace a jejich propojení – navigaci. Vizuální podobou v tomto případě myslím hlavně rozvržení jednotlivých ovládacích prvků v okně, případně zajištění základní interaktivity těchto prvků.

Mé rozhodnutí tedy bylo vydat se touto cestou a nabídnout vám tak možnost spolupodílet se na výsledném rozvržení obrazovek.

Poprosím o váš feedback

Na stránce projektu Azure desktop je k dispozici právě zmíněné sketchflow, které si můžete stáhnout k sobě na vaše PC/Notebook s nainstalovaným .net frameworkem 3.5 a spustit aplikaci AzureDeskPrototype.exe. Pro ty z vás, kdo mají možnost a nechtěli by mi třeba věřit, jsou připraveny i zdrojové kódy, které je možné zbuildovat ve VS2008 případně Expression Blend 3.

Něco málo k aplikaci

Dříve než vás požádám o zaslání připomínek něco málo k idei o fungování dané aplikace. Aplikace umí prohlížet a spravovat data uložená na vzdáleném úložišti – Azure cloudu. Pro možnost přístupu k datům je třeba aplikaci nejdříve nakonfigurovat a to přiřazením jména a klíče dané aplikace. Tato možnost se nachází na obrazovce Options.

Dále je zde obrazovka Storage, která má sloužit právě pro prohlížení a správu dat. Data mohou být, jak jsem již zmínil získávána z různých aplikací v cloudu, proto by bylo příjemné mít možnost se přepnout do dané aplikace. V dané aplikaci pak může být několik typů dat. Jsou to data umístěná v tabulkách, dále data, která byla aplikací uložena do fronty a v neposlední řadě jsou to objemná data tzv. bloby. Uživatel by měl tak mít možnost si zvolit, na která data chce momentálně nahlížet, případně je spravovat.

Jakým způsobem bude docházet k prohlážení a manipulaci s daty si nechám však na příště :-)

Sketchflow feedback

Pokud umíte s prostředím Sketchflow pro feedback, pak vás poprosím o spolupráci, zanesení vašich připomínek k mému návrhu a odeslání na moji adresu jarda [zavináč] jirava [tečka] net. Pro ty z vás, kteří vidí toto rozhraní prvně následuje krátký úvod.

Vaše připomínky zaslané do 20.9.2009 zapracuji do současného návrhu a na základě nich přidám i další scházející obrazovky.

Sketchflow aplikace – ovládání

Po spuštění programu AzureDeskPrototype vás přivítá desktopové rozhraní – v tomto případě se bude jednat o WPF aplikaci, k dispozici je i verze pro Silverlight.

SF-Main

Na pravé straně uvidíte “spuštěnou” aplikaci s rozvrřením ovládacích prvků a s navrženou infrastrukturou navigace po aplikaci. Na levé straně jsou poté nástroje pro zanesení připomínek a navigaci po jednotlivých oknech aplikace.

Jak je vidět na následujících obrázcích, máte možnost se postupně pohybovat po jednotlivých obrazovkách kliknutím na tlačítka na obrazovkách nebo v navigačním panelu na levé straně a zároveň zanést své připomínky a graficky je zvýraznit.

SF-About

About dialog

SF-Feedback

Storage dialog se zanesením informací o připomínkách (červeně zvýrazněno a doplněn text pod barevnou sadu). Po stisku tlačítka znázorňujícího složku (žlutě ohraničeno) dojde k exportu připomínek, které je možné zaslat na výše uvedenou emailovou adresu.

Po uložení souboru na disk prosím soubor odešlete na uvedenou adresu, děkuji za vaši spolupráci. :-)

Publikováno pod: .net technology , wpf
15
Sep

Entity framework a asociace na DefiningQuery

Skončili prázdniny a jak to momentálně vypadá i pěkné počasí. A tak začíná být více času se věnovat také vývojařině a odpovědím na dotazy.

Sešlo se mi, jak přes kontaktní formulář tak i z konference, hned několik zajímavých otázek, na které přeci jen není takový prostor pro odpověď přímo do diskuze a nebo je škoda je nepublikovat veřejně.

Když to vezmu pěkně popořadě, tedy pozpátku, tak zajímavý dotaz se věnoval Entity frameworku. Zadání bylo celkem jednoduché a šlo o to, že existují dvě entity, které jsou na sebe navázány asociací ve vztahu 1-m. Cílem je vytvoření property, která tento vztah zachová, ale vybere pouze posledních n záznamů. Pavel dokonce poslal i řešení, jak toho docílit přímo v programu, ale toto řešení se mu nepozdávalo

postSet.select(a=> new (a, a.Comment.OrderBy(...).Take(5))

a já se mu příliš nedivím, neboť staví na anonymních třídách a přeci jen je třeba udělat něco navíc než by bylo nutné.

Vytvoření entity a asociace

Mnou navržené řešení spočívá ve vytvoření “nové” entity a definování asociace, nazvěme ji například LastComments, která bude obsahovat pouze posledních n záznamů.

Jak tedy budeme postupovat, abychom se dobrali k finálnímu výsledku. Předpokládejme, že máme databázi, která obsahuje dvě tabulky, jenž jsou na sebe navázány ve správném vztahu.

Založíme si tedy nový projekt a vložíme do něj ADO.NET Entity Data Model. Necháme se provést průvodcem, napojíme se na zdrojovou databázi a přidáme do modelu nám známé dvě entity.

EF-PostCommentEntity

Nový EntitySet s DefiningQuery

Nyní opustíme vizuálního návrháře a vrhneme se do tajů Storage modelu. Ano, je třeba přidat nový entity set, který bude představovat pouze poslední záznamy, které získává EF z databáze. Najdeme si tedy v SSDL schématu [1] EntitySet pro naši entitu komentářů (reprezentující stranu n vztahu) a tuto zkopírujeme,

EF-SSDLBeforeEdit

z takto vytvořeného EntitySetu smažeme atributy store:Type a Schema. Dále EntitySet přejmenujeme na LastComment a do elementu umístíme element DefiningQuery a zde zapíšeme náš dotaz do databáze. Ano, dotaz vypadá obdobně jako ten, který jsem zasílal jako řešení na hádanku Tomáše Herzega.

 EF-EntitySets

Soubor ještě nezavírejte, neboť je ještě třeba přidat Entitní typ, který vznikl dotazem do databáze. Najděte si tedy entitu komentářů, zkopírujte ji a změňte ji pouze název.

EF-LastComment

To by mělo být pro tuto chvíli vše co se týká ruční editace edmx souboru a je možné se vrátit do vizuálního návrháře.

Nová entita a asociace

Nyní už nám schází jen poslední krok a můžeme používat vlastnost LastComments a to je přidání nové entity a asociace. V modelu tedy vytvoříme novou entitu a přidáme do ní potřebné vlastnosti. Na entitě Post si dále zvolíme vytvoření nové asociace, zvolte jméno a obě strany vazby, nezapomeňte vhodně pojmenovat i tzv. Navigation Property.

EF-AllEntities

Nyní si vyberte tuto nově vytvořenou asociaci a v Mapping details okně provedeme mapování jak je naznačeno na obrázku.

EF-Mapping

Tím je naše mise u konce a nyní můžeme používat tuto vlastnost v projektu.

Nebezpečí číhá všude

Kdybych nyní skončil, asi byste mě po nějaké době používání přestali mít rádi. Proto raději hned upozorním na nebezpečí, které na váš číhá.

První upozornění se týká toho, že dané řešení tak jak je zapsáno je z pohledu vývojáře neměnné. Pokud vývojář začne používat vlastnost LastComments je to správně. Nebezpečí číhá v tom, že jsme náš Storage model upravili a svázali jsme jej tak s konkrétní implementací databázového stroje, v tomto případě MS SQL Serveru 2005 a vyšší. Pokud bychom chtěli migrovat na jiný databázový stroj, je třeba změnit, zdůrazním slovo pouze, SELECT dotaz ve Storage model schématu.

Druhým nebezpečenstvím pak je, že si nejsem jist správností navrženého řešení. Mohu se pouze domnívat, že je to takto správně a doufám, že mě někdo podpoří a navržený postup potvrdí.

Samozřejmě, pokud najdete lepší řešení, které se nebude spoléhat na definici nové entity a asociace, budu rád za jeho zveřejnění.

[1] abychom se přepnuli do možnosti editovat edmx soubor, je třeba kliknout pravým tlačítkem na modelu a zvolit volbu Open with … v dialogu poté zvolit xml editor.

Publikováno pod: Linq , .net technology
7
Jun

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

Pojďme se přesunout od klávesnice ke stolům a popovídat si o vývojářských, ale také těch méně vývojářských tématech v příjemném prostředí některé z pražských restaurací.

Jestliže se chcete neformálně a přitom osobně potkat s některými z přispěvatelů konference o .net na serveru builder.cz, budete vítání v jednom z níže uvedených termínů. Jedná se o neformální společenské setkání vývojářů, se širokým záběrem témat, od těch ryze o vývoji software, ale stihneme probrat i témata jiná.

Pokud tedy máte chuť, náladu a hlavně čas, rád vás uvidím:

Kdy: 15. nebo 17.6.2009 (pondělí nebo středa)

V kolik: začátek je v 18:30

Kde: v některé z příjemných pražských restaurací, upřesním v potvrzovacím emailu

Registrace: poprosím o komentář s uvedením emailu a preferovaným termínem

Samozřejmě jsou vítání všichni, jak tváře známé, tak i zatím tváře neznámé – samozřejmě, že budete vítání i v případě, že nepříspíváte do konference, ale o .net se zajímáte.

Jelikož je akce již velice brzy, poprosím o registraci do čtvrteční půlnoci.

Publikováno pod: builder.cz , .net technology
5
Jun

asp.net MVC – když Model není Model

Tak jsem si ve svém shrnutí diskuze o asp.net MVC pěkně naběhl, když jsem vyřkl následující větu: “Model představuje data k zobrazení”.

Při tomto výroku jsem myslel především na skutečnost, že je častou chybou představit si Model jako databázi a jako takový je potom znám ve View. V takovém případě pak má View přímý přístup k databázi, což se mi nelíbí a určitě bych toto nedělal a ani nemohu doporučit (na čemž jsme se v diskuzi shodli). Už jsem však nemyslel na pokročilé vývojáře, kteří dle definic znají pod pojmem Model aplikaci/služby a přitom dokáží svůj model připravit k využití v Controlleru tak i k zobrazení bez následků ve View.

Poté, co jsem si vše nechal uležet mi vše docvaklo a zjistil jsem, že pojmenování nebylo z mé strany úplně vhodné. Tudíž je na čase se omluvit.

Takže Model, tak jak je pojímán v definici MVC není skutečně tím Modelem, který jsem vyřkl v oné větě. Pro toto mé označení by se více hodilo označení ViewModel, tak jak je pojímáno v jedné z implementací MVC a to MVVM.

Pro příště se tedy budu držet terminologie, že View zná svůj ViewModel, to samé pak platí pro komunikaci směrem od Controlleru k ViewModelu. Pouze ViewModel pak ví o Modelu. A nesmím ještě zapomenout na propojení z Controlleru na View.

To jak se právě uvedeného propojení dá využít v psaní asp.net MVC aplikace se pokusím naznačit v příštím článku. A možná se mi tak podaří ukázat, že ono pověstné přidání komentářů může znamenat změnu jen jednoho místa v … a poté změnu samotných View, tak jako by to bylo nutné udělat ve WebForms.

4
Jun

asp.net MVC Best practices – shrnutí

Ve středu večer proběhla diskuze v půlkulatém kruhu na téma asp.net MVC Best practices, kterou se mi povedlo uspořádat v prostorách Microsoftu a pozvat na ni zástupce různých technologií.

Něco málo k organizaci

Dřív než se dostanu k samotnému shrnutí získaných informací, dovolím si uvést několik málo informací k organizaci a průběhu samotné diskuze. Tato totiž dopadla nad očekávání dobře a dle reakcí účastníků to není jen můj osobní pocit, za což jsem velice rád a musím především zúčastněným poděkovat. Maličko jsem se totiž obával, když jsem sezval zástupce různých technologií, aby diskuze nesklouzla k flame-ování, ve výsledku z toho byla však konstruktivní debata trvající téměř 3 hodiny, a po ní ještě flám-ování. Je vidět, že pokud se sejdou lidé, kteří mají spoustu znalostí a zkušeností, dokáží být nad věcí a přistoupit k diskuzi konstutivně. Zároveň se pak velice snadno dokáží přizpůsobit a orientovat se i v jiné technologii, jelikož se zde řeší stejné úlohy, pomocí stejných vzorů, jen s odlišnou implementací.

Pro příště mám však jedno ponaučení, zúčastnění by se měli na takovéto diskuzi osobně představit. Přestože jsem připravil vizitky velikosti A4 se jménem a zastoupenou technologií, nebylo to dostačující. A tak David Grudl (Nette PHP) zjistil až někdy kolem půlnoci, že se zúčastnil také Michal Bláha (.NET WebForms). Zajímavá chvilka taktéž nastala při diskuzi, kdy Vlasta Vávrů (Java, PHP) se podivil nad komplexností deploymentu popisovaného Honzou Králem (Django). Zajímavé postřehy pak měli také Karel Minařík (Rails), Borek Bernard (Flex) a Daniel Kolman (.NET MVC). Musím též poděkovat Aleši Roubíčkovi a Michalu Augustýnovi za pomoc a podporu při organizaci. Samozřejmě patří dík i ostatním, kteří se zúčastnili a zapojili se do diskuze.

Ostatním, kteří měli zájem se diskuze zúčastnit, nebo mají zájem dozvědět se závěry z diskuze mám potěšující zprávu, v dohledné době proběhne přednáška na téma asp.net MVC, kde budou prezentovány závěry z uskutečněné diskuze vzešlé.

Pro nedočkavce – shrnutí MVC Best practices

Myslím, že velice detailní shrnutí již sepsal Borek Bernard v ohlédnutí z diskuze o MVC a svůj pohled na, asi jedinou flame diskuze, pak Tomáš Herzeg o rozdílech mezi WebForms a asp.net MVC.

Přidám tedy jen svůj pohled, který doufejme doplní výše uvedené články. Co jsem si odnesl z diskuze já a co mě velice potěšilo, že jsem se vesměs se svými předchozími články popisujícími použití MVVM v asp.net MVC celkem trefil do toho, jak uvažují i ostatní o přístupu k implementaci MVC principu pro webové aplikace. Právě David Grudl popisoval velice podobný scénář, který použil v Nette pomocí “plniče” Presenteru, jako jsem uvedl v článku jak vypadá ViewModel v asp.net MVC.

V hlavní roli Model

Co je třeba si uvědomit při využití jakékoliv implementace MVC je role Modelu. Jak zmínili téměř všichni přítomní, především u začínajících vývojářů je Model považován za databázi, což určitě není. Model představuje data, která jsou připravena k zobrazení. Na co určitě zapomeňte je předávání DataContextu do View, pokud chcete využít třeba LINQ2SQL nebo Entity Framework. Maličko lepší službu už uděláte v případě, že předáte jen vygenerované datové objekty, na mnoha malých webech to bude dostačující. Jestliže však uvažujete o něčem větším, vytvořte si vhodný view model, který bude respektovat potřeby pro zobrazování v aplikaci, nikoliv potřeby relační databáze. Do modelu se pak nebojte zahrnout i podpůrné vlastnoti vhodné při zobrazování dat.

Jednoduchý Controller

Citovat Davida si dovolil již Borek, já mohu jen souhlasit. Controller by měl být co nejjednodušší. Měl by se postarat jen o výběr vhodného ViewModelu (Presenteru), zvalidovat vstupní data a vybrat šablonu (View), která provede zobrazení dat. Případně se samozřejmě postará o přesměrování na jinou akci, což je jen o tom, že vybere jiný ViewModel a jinou šablonu, která se zobrazí.

Pasivní View

Přesně tak, nesnažte se do View vkládat složitější logiku než je jen vypsání dat na potřebná místa. Šablony v asp.net MVC mohou svádět k tomu je vytvořit aktivní a manipulovat zde s Modelem, obzvláště pak v případě, že si do View předáme potřebné objekty typu DataContext. Dobrým řešením by mohlo být použití takového ViewEngine, který dovoluje pouze deklarativní zápis, případně komponentové poskládání stránky – obdobně jako bylo představováno frameworkem Django.

Nenecháme si to pro sebe?!

Samozřejmě je toho víc a výše zmíněné je jen to hlavní co mi utkvělo v paměti. O další informace se budu chtít s vámi podělit. Kdy to konkrétně bude ještě nevím, ale určitě sledujte vypisované akce. A není to vše, jak jsem se již zmiňoval v úvodu, snad všichni pozvaní vývojáři byli uspořádáním takovéto akce nadšeni a rádi se zúčastní obdobných diskuzí. A jelikož se více jak půl hodinu taktéž diskutovalo o testování aplikací, předběžně jsme se domluvili na tomto tématu. Představa je formou panelové diskuze, tudíž pokud bude mít někdo zájem, určitě se bude moci zúčastnit.

Budu se tedy těšit na brzkou viděnou se všemi zájemci o vývoj pomocí asp.net MVC.

25
May

WPF Binding bez codebehind

Celkem zajímavý dotaz padl v konferenci o .net na serveru builder.cz. V krátkosti se jednalo o změnu datového zdroje nabindovaného na ListView při změně vybrané položky jiného ListView.

Varianta codebehind

V dotazu bylo poukazováno na obsluhu události SelectionChanged, ve které chtěl tazatel řešit změnu bindování na jiný deklarovaný zdroj ve Window.Resources, konkrétně různě naplněný XmlDataProvider.

Samozřejmě by toto provázání bylo taktéž možné, ale z vlastní zkušenosti a vývoje wpf aplikací jsem zjistil, že používání codebehind souboru není většinou nutné a je možné vše deklarovat pomocí XAML. Codebehind je tak ve větší míře využíván jen při tvorbě vlastních Control.

Varianta bez codebehind

Tazateli jsem tedy zaslal odkaz na příspěvek [Selecting the Detail Level to View at Runtime in WPF] publikovaný na CodeProject od Josh Smith, který se věnoval bindování různých deklarovaných template dle uživatelského výběru. Principiálně tedy velice podobný problém. Martin to tak neviděl a tak jsem se rozhodl konkrétní případ vytvořit a publikovat. Jelikož je však třeba bližšího komentáře, ponechal jsem si odpověď jako krátké povídání.

Postup vytvoření aplikace splňující zadání

Začal jsem s čistým projektem typu WPF aplikace. První na řadě tak byla deklarace datových zdrojů – XmlDataProviderů a naplnění daty.

Deklarace datových zdrojů

<XmlDataProvider x:Key="products" XPath="root/datas">
            <x:XData>
                <root xmlns="">
                    <datas>
                        <data id="a1">a</data>
                        <data id="a2">b</data>
                        <data id="a3">c</data>
                    </datas>
                </root>
            </x:XData>
        </XmlDataProvider>
        <XmlDataProvider x:Key="a1" XPath="root/datas">
            <x:XData>
                <root xmlns="">
                    <datas>
                    <data>1aa</data>
                    <data>1bb</data>
                    <data>1cc</data>
                    </datas>
                </root>
            </x:XData>
        </XmlDataProvider>
        <XmlDataProvider x:Key="a2" XPath="root/datas">
            <x:XData>
                <root xmlns="">
                    <datas>
                    <data>2aa</data>
                    <data>2bb</data>
                    <data>2cc</data>
                    </datas>
                </root>
            </x:XData>
        </XmlDataProvider>
        <XmlDataProvider x:Key="a3" XPath="root/datas">
            <x:XData>
                <root xmlns="">
                    <datas>
                    <data>3aa</data>
                    <data>3bb</data>
                    <data>3cc</data>
                    </datas>
                </root>
            </x:XData>
        </XmlDataProvider>

Deklaraci datových zdrojů a přiřazení jim příslušných identifíkátorů jsem vložil do Window.Resources elementu tak, aby tyto zdroje byly dostupné v celém objektu okna. Tady musím zmínit, že názvy datových zdrojů, které budou měněny po výběru jsem definoval shodné s hlavním zdrojem dat. Toto samozřejmě není nutné, jde jen o to, mít jasně definovaný převodní můstek pro výběr správného zdroje.

Vzhled aplikace

Následovala deklarace aplikace, zvolil jsem StackPanel, do kterého jsem postupně přidával jednotlivé prvky. Nesmí chybět nějaký nadpisek aplikace, abychom neměli jen holé okno. Následuje pak deklarace prvního ListBoxu – jakožto jednodušší varianty (předka) pro ListView. Tento ListBox je nabindován na hlavní datový zdroj. Zároveň definuje vlastní DataTemplate, který se stará o vizuální zobrazení dat v prvku.

        <ListBox Width="400" Height="200" Background="Honeydew" x:Name="prod">
            <ListBox.ItemsSource>
                <Binding Source="{StaticResource products}" XPath="*" />
            </ListBox.ItemsSource>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock FontSize="12" Foreground="Red">
                      <TextBlock.Text>
                        <Binding XPath="." />
                      </TextBlock.Text>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

V tomto případě jsem použil expandovaný zápis pro binding i když by se samozřejmě dal použít i inline styl. Druhý deklarovaný ListBox je jen o něco málo složitější, ale ukrývá v sobě hlavní sílu WPF a to MultiBinding a využití IValueConverter resp. IMultiValueConverter.

IMultiValueConverter – srdce bindingu pro řešení zadání

Dříve než sem napíšu i deklaraci druhého ListBoxu, musím se zmínit o srdci celého řešení a to je vytvoření konverteru, který zajistí vyhledání datového zdroje v Resources a jeho navrácení. Pro vyhledání jakéhokoliv pojmenovaného zdroje je možné použít metodu FindResource, případně její rozšířenou variantu TryFindResource lišící se pouze v tom, že nevyvolá Exception v případě, že daný klíč není nalezen v Resources. Pro získání daného zdroje pak potřebujeme získat objekt, který tento zdroj vlastní v tomto případě objekt Window. Zároveň potřebujeme mít k dispozici i vybranou hodnotu prvního ListBoxu.

Jelikož potřebujeme dvě hodnoty, není možné využít jednoduchý IValueConverter, ale musíme použít IMultiValueConverter, který se liší pouze tím, že přebírá do metody Convert pole hodnot.

Jak tedy vypadá kód našeho konverteru:

    public class ResourceKeyConverter: IMultiValueConverter {

        #region Implementation of IMultiValueConverter

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
            var fe = values[1] as FrameworkElement;
            var val = values[0] as XmlNode;
            if ((fe != null) && (val != null)) {
                var resource = fe.TryFindResource(val.Attributes["id"].Value) as XmlDataProvider;
                return resource;
            }
            return null;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
            throw new NotImplementedException();
        }

        #endregion
    }

Jak je vidět, je to velice jednoduché, samozřejmě je třeba si domyslet ještě i další kontroly, které by bylo vhodné provést.

Binding ListBoxu dle výběru

Nyní se tedy můžeme dostat k deklaraci ListBoxu, který bude obsahovat měněná data z různých datových zdrojů. Jedná se o stejný ListBox, který je definován v prvním případě, rozdílem je pouze zmíněný MultiBinding, který předává konverteru vybranou hodnotu prvního ListBoxu a zároveň i objekt, který drží Resources, tedy v tomto případě pojmenované hlavní okno.

        <ListBox Width="400" Background="AntiqueWhite" ItemsSource="{Binding XPath=*}">
            <ListBox.DataContext>
                <MultiBinding Converter="{StaticResource rsKey}">
                    <MultiBinding.Bindings>
                        <Binding ElementName="prod" Path="SelectedItem" />
                        <Binding RelativeSource="{RelativeSource  AncestorType={x:Type Window}}" />
                    </MultiBinding.Bindings>
                </MultiBinding>
            </ListBox.DataContext>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock FontSize="12" Foreground="Red">
                      <TextBlock.Text>
                        <Binding XPath="." />
                      </TextBlock.Text>
                    </TextBlock>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

Důležitým krokem v tomto případě je, deklarace a registrace našeho konverteru do zdrojů tak, aby byl k dispozici pro použití v deklaracích u bindingu. To provedeme rovněž v elementu Window.Resources a specifikujeme pro něj klíč. Taktéž je nutné deklarovat namespace, ve kterém se náš konverter nachází.

<WpfBinding:ResourceKeyConverter x:Key="rsKey" />

Stačí jen spustit

Jsme u posledního kroku a to je spuštění aplikace, pokud jsme postupovali správně, dostaneme požadovaný výsledek. Z předchozího povídání je vidět, že pro toto zadání není nutné používat codebehind a je možné téměř všechnu logiku deklarovat za pomoci XAML a vhodně napsaného konverteru, který může být znovupoužit.

Navržené řešení nemusí být optimální a pouze reflektuje dané zadání. Osobně bych se k danému problému snažil postavit v jiném duchu a využil v hojné míře návrhového vzoru Model-View-ViewModel, který používám při tvorbě WPF aplikací. Na druhou stranu se mi toto řešení jeví jako vhodnější, než obsluhovat události jednotlivých prvků v codebehing a snažit se na ně reagovat.

Projekt ukázkové aplikace ke stažení:

Publikováno pod: builder.cz , code snippet , .net technology , wpf
24
May

asp.net MVC Best practices - pozvánka

Také se zajímáte o vývoj za pomoci MVC vzoru. Máte k tomuto přístupu k vývoji prezentační vrstvy nějaké otázky nebo si naopak myslíte, že byste mohli přispět svojí radou nebo zkušeností?

Potom budu rád, pokud se registrujete na akci asp.net MVC Best practices a svoji motivaci připíšete do poznámky.

Popis akce

K diskuzi jsou přizváni též vývojáři zastupující technologie nespadající pod .net, avšak jejich vývoj je též založen na principu návrhového vzoru MVC. Cílem diskuze je najít vhodné postupy při vývoji webových aplikací, které využívají principu MVC a odvozených návrhových vzorů tak, aby se dosáhlo efektivního vývoje aplikace, která dovoluje snadné úpravy a rozšiřitelnost. Závěry, rady a postřehy z této diskuze by měli sloužit nejen začátečníkům v orientaci při vývoji webových aplikací. Diskutující se též seznámí s implementací MVC v jiných technologiích než je asp.net. Důležitým předpokladem pro účast je tak znalost vývoje pomocí MVC návrhového vzoru, případně jeho odvozenin.

Přizvaní hosté

David Grudl, Jan Král, Vlastimil Vávrů, Michal Bláha, Borek Bernard, Aleš Roubíček, Michal Augustýn, Karel Minařík a další

1
May

.NET RIA Services – přednáška

Před týdnem jsem měl v prostorách české pobočky Microsoftu přednášku na téma .NET RIA Services, kde jsem se snažil představit tento nástroj pro snadnější vývoj RIA aplikací.

Slíbil jsem, že zdrojové kódy, které jsem z velké části odprezentoval na přednášce, zpřístupním, abyste měli možnost nahlédnout pod pokličku této technologii pro snadnější tvorbu data entry aplikací.

Zdrojové kódy aplikace obsahují připravovanou, avšak ne celou odprezentovanou, RIA aplikaci.  Před spuštěním aplikace budete muset do vývojového prostředí doinstalovat:

  • Silverlight 3 Tools Beta 1 for Visual Studio 2008 – nahrazuje Silverlight 2, proto doporučuji instalovat do testovacího prostředí např. Virtual PC
  • .NET RIA Services March ‘09 Preview

Součástí zdrojových kódů jsou i scripty pro vytvoření databáze.

V nejbližší době se pokusím připravit několik příspěvků na téma .NET RIA Services a tvorba data entry aplikací s využitím Silverlight 3.

V případě otázek jsem připraven je zodpovědět.

10
Apr

Jak vypadá ViewModel v asp.net MVC

Při psaní úvodního článku, ve kterém jsem se věnoval postřehům při vývoji asp.net MVC aplikace jsem si ani nepomyslel, že vydám i druhý článek, který bude popisovat Model-View-ViewModel upravený vzor pro takovou aplikaci. A už vůbec to, že bych se rozhodl ke psaní článku třetího o tom, jak vlastně taková třída ViewModel v mém podání vypadá.

Okolnosti tomu však chtěli a tak jsem zde s dalším pokračováním na rozpracované téma. Tentokrát se pokusím osvětlit, jak vypadá třída ViewModel v mém podání zasazená do asp.net MVC aplikace.

ViewModel

Jak jsem již popsal, třída ViewModel zprostředkovává data a komunikuje se sevisními objekty aplikace a zároveň poskytuje data aplikace pro View. Zároveň pak upravuje tato data, aby s nimi ve View byla snazší práce a View mohlo být velice jednoduché a nevykonávalo žádnou logiku. Ještě neopomenu zmínit jednu věc, že k vytvoření konkrétní instance ViewModel používám IoC/DI container, tudíž servisní objekty jsou injektovány a o jejich existenci tak nemusí mít Controller ponětí.

Zkusím projít popisem tak, jak většinou prochází takový normální požadavek na získání informací a jejich editaci a to pro jeden datový objekt.

Akce Controlleru vypadá nějak takto

public ActionResult Update(int id) {
    var model = Container.Resolve<ProductDetailViewModel>();
    model.Load(id);
    return View(model);
}

Odpovídající třída ViewModelu pak nějak takto

public class ProductDetailViewModel {
    private readonly IProductService _productService;
    public ProductDetailViewModel(IProductService productService) {
        _productService = productService;
    }
    
    public void Load(int id) {
        Product = _productService.Get(id);
    }
    
    public ProductEntity Product {
        get;
        private set;
    }
    
    public bool IsProductLoaded {
        get { return Product != null; }
    }
}

Pro jednoduchost jsem momentálně odstranil další potřebné servisní objekty o kterých jsem se zmiňoval již dříve. Například providera na TempDataDictionary. Zároveň je vidět, že ProductDetailViewModel obsahuje i další vlastnosti, které jsou použity ve View a odpadá nám tak nutnost testování a rozhodování se na úrovni View.

Nyní přejdu k akci, kdy uživatel žádá o aktualizaci takto poskytnutého záznamu, který zaktualizoval.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update(int id, FormCollection formCollection) {
    var model = Container.Resolve<ProductDetailViewModel>();
    model.Load(id);
    if (TryUpdateModel(model.Product, "Product", null, new string[] {"Id"})) {
        if (ModelState.IsValid) {
            model.Save();
            return RedirectToAction("Get", new { id = id});
        }
    }
    return View(model);
}

Jak je vidět, téměř nic se nezměnilo, jen přibyla metoda Save() na našem ViewModelu, která zpropaguje požadavek na servisní vrstvu.  Celé by to šlo samozřejmě ještě upravit tak, že by metoda Save vracela výjimku v případě, že by se nepodařilo záznam uložit a došlo by k znovupožadavku na editaci. Je však na samotné logice aplikace, jak se s takovou chybou vypořádá a zda nabídne uživateli opět možnost editace a odstranění problému, nebo jej přesune na jinou stránku.

Důležitou součástí celého procesu se tak stává ModelBinder, který může zároveň provést validaci vstupních dat oproti business pravidlům.

Spolupráce s ModelBinder

Výše uvedené je celkem pěkný postup, ale stále zde je ještě spousta kroků, které se mohou přesunout, abychom se mohli soustředit jen na samotné akce a pokud možno se co nejvíce přiblížili k pouhému vyvolávání metod na ViewModelem, tak jako se vyvolávají události ve WPF aplikaci při použití vzoru MVVM.

K tomu však potřebujeme maličko lepší spolupráci ModelBinderu, než která nám je nabízena prostřednictvím výchozího DefaultModelBinderu. Hlavní úlohou námi definovaného ModelBinderu je vytvoření instance ViewModelu a validace vstupních dat. Samozřejmě si zde můžeme připsat i další logiku bindování na data.

Takový ModelBinder pro náš ViewModel k detailu produktů může vypadat následovně:

public class ProductDetailViewModelBinder: DefaultModelBinder {
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        bindingContext.Model = Container.Resolve<ProductDetailViewModel>();
        var id = int.Parse(bindingContext.ValueProvider["Product.Id"].AttemptedValue);
        bindingContext.Model.Load(id);
        return base.BindModel(controllerContext, bindingContext);
    }
}
Samozřejmě opět odhlížím od kontrol, které by bylo potřeba doplnit. Zároveň by bylo vhodné doplnit validaci nabindovaných dat oproti business pravidlům, což je pro zjednodušení vynecháno.

Akce v příslušném Controlleru se nám tedy rázem zjednoduší a její implementace bude následující:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update([Bind]ProductDetailViewModel model) {
    if (ModelState.IsValid) {
        model.Save();
        return RedirectToAction("Get", new { id = model.Product.Id});
    }
    return View(model);
}

Což už je myslím akceptovatelný stav. Samozřejmě bude záležet na okolnostech a celkovém chápání aplikace. Neboť tento případ skrývá před vývojářem samotné naplnění modelu daty třídy Product, což je na druhou stranu obdobný případ, jaký nastává ve WPF aplikaci, kdy nedochází ke ztrátě stavu a pracujeme již s existující instancí naplněnou daty.

Před cílovou rovinkou

Už je mi celkem jasné, že jsem se nedostal ani před cílovou rovinku a vyvstaly další otázky. Třeba jak řeším právě předávání dočasných dat v TempDataDictionary a jak dochází k jejímu injektování do ViewModelu. Takže u tří článků určitě nezůstane. V příštím článku se tak pokusím soustředit se na tuto oblast a případně zodpovědět vložené dotazy.