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

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

WPF Frame jako WebBrowser

Berte tento příspěvek spíše jako pomyslné nakousnutí jablka, ve kterém se snažím odhalit, zda obsahuje červa, nebo je čisté a já mám jen špatnou chuť.

V jedné aplikaci, kterou vyvíjím ve WPF verze 3.0 jsem byl nucen přistupovat k webovým stránkám. Moje rozhodnutí tak padlo na Element Frame, kterým je možné zpřístupnit HTML obsah. Jelikož se mi však nelíbila navigační tlačítka – spíše nezapadla do vizuálního prostředí aplikace – skryl jsem tato pomocí vlastnosti NavigationUIVisibility.

Navigace na první stránku pak probíhá programově a z této úvodní stránky se již uživatel může rozhodnout sám, jakým směrem se vydá a po jakém linku budou vést jeho cesty. Důležité je v této chvíli říct, že bylo zapotřetí uživateli dát možnost se vrátit zpět na onu výchozí stránku.

To jsem si říkal, že bude velice jednoduché a jednoduše provedu programové volání metody Navigate(). Zde jsem však nečekaně narazil. Při debugu jsem poté zjistil, že Frame stále obsahuje ve vlastnosti Uri programově zadanou výchozí stránku, byť je zobrazena stránka jiná. Obdobně je na tom i NavigationService vlastnost. Zde se však objevil první rozpor, jelikož je nastavena vlastnost CanGoBack na hodnotu true, signalizující, že je možné přejít zpět – a to přesto, že URL se nikterak nezměnilo, kdežto obsah stránky ano. Stejně tak byly marné jakékoli pokusy vyvolat akci typu GoBack() nad Framem.

V Content je schován WebBrowser

Mé pátrání tak pokračovalo dále a zjistil jsem, že ve vnořené vlastnosti Content pro NavigationService je vložen objekt WebBrowser, ano ta komponenta, která se nachází v .net 2.0 pro WinForms, a je tak hostovaná v prostředí WPF. Po několika pokusech jsem pak zjistil, že právě tento WebBrowser je ochoten reagovat na moje příkazy.

Stačilo tedy jednoduché přetypování a získání WebBrowseru a jednoduchá práce přímo s tímto objektem.

Ouha

Přišla tedy na řadu kompilace a distribuce nové verze aplikace. Jenže ouha, vypadá to, že se něco nepovedlo. V průběhu několika málo okamžiků jsem měl ve své email schránce znění Exception chyby

Could not load type 'System.Windows.Controls.WebBrowser' from assembly 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

Což mě přiznám se maličko, no dost, zarazilo a jsem v rozpacích, kde je co špatně. Jelikož zde bohužel platí ono známe “Works on my machine.

Řešení

Vhodné řešení tohoto problému jsem zatím nenašel. Moje cesta se začala ubírat jiným směrem a na řadu přišlo náhradní řešení, které určitě není optimální. Ještě bych asi měl podotknout, že cílový počítač obsahuje IE6.0 + SP. Věděl by někdo, jakým směrem se vydat v případném dalším bádání?

Publikováno pod: .net technology , wpf
4
Mar

WPF Photo organizer I

WPF aplikace jistě začnou v dohledné době okupovat naše PC miláčky. Několik takových aplikací se již pomalu začíná objevovat, jedná se jak o čtečky novinových článků, tak i ostatní neméně zajímavé aplikace. Ostatně, ty zajímavé můžete nalézt v přehledu na channel 9.

Co však u takové aplikace, uvedené ve zmíněném přehledu chybí, je popis jak ji vytvořit. Ano, takový jednoduchý, srozumitelný návod, pro nás vývojáře, kteří se chceme zabývat vývojem aplikací pro WPF, tedy tvorbou UI v jazyce XAML. Někdo jistě může namítnout, že příkladů na netu existuje dostatek, ale přiznám se, že popsaný vývoj jedné aplikace jsem nikde nenašel, vždy se jednalo jenom o samostatné části, vytvoření nebo nastylování Buttonu, případně seriál o WPF jako takovém, třeba jako ten na vývojáři. Jelikož je WPF zajímvavá technologie, pustil jsem se do tvorby jednoduchého organizátoru fotografií. Jelikož jsem si říkal, že pro vývojáře není důležitý jen výsledný efekt, ale i postup, jak se k cíly dostat, rozhodl jsem se s Vámi podělit a v několika příspěvcích tak představit tvorbu takové aplikace.

Cíl mého snažení

Samozřejmě, že je možné stáhnout si nejrůznější organizátory fotografií, tak proč jsem se rozhodl zrovna pro aplikaci takového typu? Jedním z kriterií bylo, že pro takovou aplikaci není třeba příliš programování ve vrstvě aplikační a také databázové logiky. Zato je možné představit nejrůznější možnosti, které nabízí WPF, takže většina kódu může být deklarována za pomoci XAML. Na druhou stranu jsem nechtěl, aby byla aplikace přeplácána různými efekty, jako je reflexe apod. to u mě určitě nenajdete.

Jako jedno z vylepšení, které se příliš u podobných aplikací nevidí a které si myslím využiji, je možnost označit fotografii k tisku a uvedení počtu kopií. Jistě to znáte, chcete si některé své digitální fotografie nechat vytisknout a tápete, jak si je označit a poznamenat k nim, v kolika kopiích je chcete mít (obzvláště důležité v současné chvíli, kdy nechávám tisknout fotky Davídka ;-) ).

Co všechno aplikace umí

Pojďme se tedy podívat na to, jakou funkčností jsem tento organizátor fotografií vybavil.

Import fotografií
  • k importu fotografií do aplikace dojde pomocí výběru adresáře na disku
  • zároveň s tím, se daný import pojmenuje a tak vznikne sada obrázků
Informace k fotografii

v průběhu importu se z fotografie zjišťují některé základní informace a EXIF informace jako:

název, datum pořízení, iso, clona, čas, model fotoaparátu ...

Fotografii je možné označit popiskem a také ji přiřadit tagy.

Základní pohledy
  • pohled na fotografie podle složky importu - vzniklé sady
  • pohled na fotografie podle jejich doby pořízení - zajištěno pomocí stromového menu
  • pohled na fotografie podle definovaných tagů - tagy je možné přiřazovat obrázkům během importu, tak i v průběhu prohlížení
  • pohled na jednotlivou fotografii dle výběru
  • tzv. paper tray pohled, kdy se zobrazují pouze fotografie k tisku

Aplikace během importu vytváří malé náhledy na obrázky a tyto ukládá do aplikačního adresáře. Zároveň jsou veškeré zjištěné informace k fotografii ukládány do databáze. Pro tyto účely jsem zvolil databázi SQL Server Compact edition, která by měla svým výkonem dostačovat pro všechny případy a zároveň je velice jednoduchá na instalaci.

Je důležité se zmínit o tom, že se zdrojovou fotografií se nemanipuluje. Fotografie vložené do paper tray je možné vyexportovat pro úpravy, tak aby nebyla dotčena původní fotografie.

Doufám, že jsem Vás naladil a nalákal na pokračování, které již nebude jen o teorii. Zároveň, pokud máte nějakou připomínku nebo dotaz, budu rád za komentář. Díky

Publikováno pod: wpf , .net technology