\

Školení Návrhové vzory, OOP a UML


 Friday, 19 May 2006
Sloupec v GridView s potvrzením vymazání záznamu (na klientovi)

Jestliže chcete mít v GridView sloupec, který uživatele požádá na klientovi (s využitím JavaScriptu) o potvrzeni smazání záznamu, je doporučeno používat TemplateField, jehož šablona ItemTemplate obsahuje ve vlastnosti OnClientClick tlačítka klientský kód.

<asp:TemplateField ShowHeader="False">

   <ItemTemplate>

      <asp:ImageButton ID="ImageButton1" runat="server" CausesValidation="False" CommandName="Delete" ImageUrl="~/Images/delete.gif" OnClientClick="javascript:return confirm('Opravdu smazat záznam?');" />

   </ItemTemplate>

</asp:TemplateField>

ButtonField by byl sice vhodnější, ale tvůrci ASP.NET zadání kódu v JavaScriptu pro ButtonField nepodporují. Třída ButtonField nenabízí ani přístup k vlastnostem prvku Button, který je vyrenderován na každém řádku GridView.

Chceme-li napsat svůj vlastní typový sloupec pro mazání záznamů, který budeme používat ve všech svých projektech, použijeme třídu ButtonField alespoň jako předka svého nového sloupce a lehce "dirty" kódem v v přepsané metodě InitializeCell přidáme tlačítku vytvořenému v "našem" sloupci pro každý řádek GridView jednoduchý kód v JavaScriptu, jenž bude vyžadovat od uživatele potvrzení smazání záznamu.

    /// <summary>
    /// Nový typ sloupce pro GridView obsahující tlačítko pro smazání záznamu s potvrzením na klientovi (JS)
    /// </summary>
    public class DeleteButtonField : ButtonField
    {
        #region Private constants
        private const string DEFAULT_CONFIRM_MESSAGE = "Opravdu smazat záznam?";
        private const string DELETE_COMMAND = "Delete";
        private const string DELETE_JS = "javascript: if (!confirm('{0}')) return false;";
        #endregion Private constants

        public DeleteButtonField() : base()
        {

        }

        #region Public properties
        /// <summary>
        ///Text varování, které se má zobrazit uživateli při pokusu vymazat záznam
        /// </summary>
        public string ConfirmMessage
        {
            get
            {
                string confirmMessage = (string)ViewState["ConfirmMessage"];

                if (confirmMessage == null)
                {
                    return DEFAULT_CONFIRM_MESSAGE;
                }

                return (confirmMessage);
            }

            set
            {
                ViewState["ConfirmMessage"] = value;
            }
        }
        #endregion Public properties

        #region Public properties

        /// <summary>
        /// Metoda volaná při incializaci buňky Gridu
        /// </summary>
        /// <param name="cell">Inicializovaná buňka</param>
        /// <param name="cellType">Typ buňky</param>
        /// <param name="rowState">Stav řádku buňky</param>
        /// <param name="rowIndex">Index řádku buňky</param>
        public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
        {
            base.InitializeCell(cell, cellType, rowState, rowIndex);
            if (cell.Controls.Count > 0)
            {
                IButtonControl control = cell.Controls[0] as IButtonControl;

                if (control != null)
                {
                    control.CommandName = DELETE_COMMAND;
                  
                    LinkButton lb = control as LinkButton;
                    Button btn = control as Button;
                    ImageButton iBtn = control as ImageButton;

                    string fullConfirmMessage = String.Format(DELETE_JS, ConfirmMessage);
                    if (lb != null)
                    {
                        lb.OnClientClick = fullConfirmMessage;
                    }

                    else if (btn != null)
                    {
                        btn.OnClientClick = fullConfirmMessage;
                    }
                    
                    else if (iBtn != null)
                    {
                        iBtn.OnClientClick = fullConfirmMessage;
                    }
                }
            }
        }
        #endregion Public methods
    }

Kód není nijak složitý. Kromě konstant, jejichž význam je dostatečně zřejmý z jejich názvu, máme v našem novém sloupci vlastnost ConfirmMessage, která obsahuje text zobrazovaný v dialogu pro potvrzení smazání záznamu. V metodě InitializeCell nejdříve zavoláme implementaci InitializeCell třídy ButtonField. Poté zjistíme, jestli buňka gridu (cell) obsahuje nějaké ovládací prvky. Jestliže ne, byla metoda volána pro řádek reprezentující záhlaví nebo zápatí gridu, a v ní žádné tlačítko nebude. Když buňka obsahuje alespoň jeden ovládací prvek, zjistíme zda první prvek v kolekci1 je typu IButtonControl (rozhraní IButtonControl implementují třídy LinkButton, Button i ImageButton) a nastavíme jeho vlastnost CommandName na text Delete. Jak asi víte, řetězec "Delete" je jedním z příkazů, které GridView rozeznává a speciálně ošetřuje, takže při bublání událost Click tlačítka s CommandName nastaveným na "Delete" je vyvolána událost RowDeleting (a případně další) místo generické události RowCommand.

Protože rozhraní IButtonControl nenabízí vlastnost OnClientClick pro zadání potvrzujícího kódu v Javascriptu, musíme přetypovat na konkrétní třídu Button a poté teprve můžeme použít vlastnost OnClientClick. Další "dirty" kód :-) - byl bych raději, kdyby byla vlastnost OnClientClick přímo součástí rozhraní IButtonControl, anebo by mohl existovat společný abstraktní předek s vlastností OnClientClick pro třídy ImageButton, LinkButton a Button.

Nový sloupec ve svém projektu použijete takto:

Zaregistrujete nový sloupec na stránce jako běžný serverový ovládací prvek zadáním jména jeho assembly, jmenného prostoru a rezervací prefixu značek pro své prvky v direktivě @Register.

<%@ Register Assembly="Rstein.Web.Ui" Namespace="Rstein.Web.Ui" TagPrefix="custom" %>

Sloupec přidejte do kolekce Columns prvku GridView a nastavte dle svých požadavků vlastnosti sloupce. 

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnRowDeleting="GridView1_RowDeleting">

   <Columns>

         <custom:DeleteButtonField Text="Smazat" ButtonType="Button" ConfirmMessage="Smazat záznam?"/>

   </Columns>

</asp:GridView>

Příště si ukážeme, jak podobné sloupce pro Grid udělat lépe s využitím šablon vytvořených v kódu a také doplníme pro své sloupce kompletní podporu pro design time.

 

  1. Zde je ten zmiňovaný "dirty" postup. I když jsem si ověřil Reflectorem, že prvním prvkem kolekce je vždy IButtonControl vytvářený třídou ButtonColumn, jde o typický případ svazování svého kódu s kódem, jehož  změny nemáte pod kontrolou a přitom se nespoléháte jen na jeho "typově bezpečné" veřejné API, takže se v dalších verzích můžete dočkat nepříjemných překvapení  :( 


Friday, 19 May 2006 17:44:04 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  .NET Framework | ASP.NET


 Thursday, 11 May 2006
První zkušenosti s navigačním programem iGO

Program iGO má nejen exotický maďarský původ, ale také jde v poslední verzi o slušně zpracovaný navigační systém, který vás bez větších problémů dovede tam, kam máte namířeno. A hlavně jako u všech dobrých navigací dorazíte do cílového místa, aniž byste předtím museli vytvářet itinerář cesty hledáním v tištěném Autoatlasu nebo internetové mapě, a k rodinné pohodě přispěje i tím, že už nemusíte za jízdy manželce v roli navigátora po několikerém špatném odbočení nervózně a zvýšeným hlasem vysvětlovat, jak se pozná na papírové mapě, jestli máte odbočit vpravo či vlevo. ;-)

I když jsem k novému programu přistupoval s despektem, musím říci, že moje obavy z práce neznámých maďarských programátorů byly pouhé předsudky a samotné iGO se může i přes drobné chybky v kvalitě navigace směle měřit s programy jako jsou Dynavix či TomTom.

Všechny možné grafické a funkční serepetičky navigace oceníte jen a pouze při práci s navigací v křesle domova, protože za jízdy těžko budete obdïvovat krásné textury objektů na dispĺeji. Plech vašeho vozu by totiž mohl být za chvíli ilustrací fyzikálního zákona pojednávajícího o následcích srážky s pohyblivými i statickými objekty v reálném světě. Proto mám na navigační programy tyto tři hlavní požadavky.

  1. Nejdůležitější součástí každého navigačního programu je intuitivní hlasová navigace - ideální hlasová navigace po celou dobu jízdy přichází s tak přesnými instrukcemi, že se uživatel nemusí ani jednou podívat na displej, aby věděl, jak má na křižovatce zabočit. To znamená, že hlasová navigace by dnes již neměla mít jen jednoduché instrukce ve stylu "zabočte vlevo", "zabočte vpravo" nebo "po 150 m zabočte doprava", ale měla by navigovat uživatele například i v křižovatkách, kde po sobě rychle následují dvě odbočky doprava a jasně mu říci, kterou odbočku má zvolit. Při jízdě po hlavní silnici, kdy dodatková tabulka 'opravdový tvar křižovatky' u značky 'Hlavní silnice' sděluje, že hlavní silnice pokračuje doleva či doprava, musí hlasová navigace v dostatečném předstihu sdělit "jeďte po hlavní silnici" či "pokračujte po hlavní silnici - mírně vpravo", abyste se opět nemuseli o dalším směru jízdy ("rovně po vedlejší" nebo "dále po hlavní") rozhodovat podle toho, co je momentálně zobrazeno na displeji. 
  2. Žádný navigační program zatím s ideální hlasovou navigací nepřišel, a proto se občas při složitějších křižovatkách kouknutí na displej PDA nevyhneme. Abychom zorientováním se v informacích na displeji netrávili zbytečně mnoho času, je nutné, aby navigační program zobrazoval všechny podstatné informace, perfektně vykreslil schéma následujího manévru a nastavil měřítko (zoom) mapy tak, abychom ihned dokázali "namapovat" reálnou křižovatku na zobrazení křížovatky na displeji a věděli, jak ji máme projet. Za standard již považuji 3D pohled. Když je 3D pohled dobře naprogramován, je orientace v mapě citelně jednodušší než při méně přirozeném "plochém" 2D pohledu. Přeplácaná grafika orientaci na mapě  stěžuje - čím více zbytečných detailů, které oceníte snad jen v hrách typu Need For Speed, tím pomalejší orientace v mapě. Od podrobností abstrahující a jen schematické zobrazení míst, kterými právě projíždíte, je pro navigaci mnohem přínosnější než všemi barvami a grafickými efekty opentlená mapa. 
  3.  I když dnes již snad každý program trochu alibisticky zobrazuje upozornění, které nás důrazně varuje před používáním programu za jízdy, občas se přeci jen ovládání programu při řízení nevyhneme. Když se rozhodneme někde naobědvat, budeme chtít rychle vyhledat v zájmových bodech (POI) nejbližší restauraci a nechat se k ní navigovat. Je proto důležité, aby menu bylo přehledné a aby ikonky jednotlivých funkcí v něm byly dostatečně velké. Ikonky musí být čitelné na displeji PDA i z větší dálky a celé menu musí být ovladatelné dotykem prstu, jehož průměr bývá u většiny normálně vyvinutých jedinců přeci jen o něco větší než průměr stylu. K bezpečnému ovládání za jízdy také velkou měrou přispívá velikost tlačítek na softwarové klávesnici pro zadávání názvů měst, ulic a filtrování seznamu zobrazených POI.

Jak si poradí iGO s těmito požadavky ?

Hlasová navigace v iGo je na slušné úrovni. Na výběr máte mužský i ženský hlas v češtině, slovenštině a dalších jazycích. Já jsem většinu času jezdil s navigací v anglickém jazyce, protože mi angličtina přišla příjemnější a méně "strojová" než čeština a slovenština.

Místo zmatených hlášek ve městě s mnoha bočními uličkami, které pouze říkají, co máte udělat za 150 m, ale již Vám nesdělí, jak máte těch 150 m v autě změřit, se dovíte, že  máte zabočit vpravo do následující (první, druhé) ulice. Všechna hlášení jsou také vydávána s dostatečným předstihem  - občas si ale říkáte, že po nájezdu na dálnici není nutné ihned vědět, co se stane za 40 Km, a i by podle mě mohl být zredukován počet hlášení v různých vzdálenostech od odbočky.

Při přímém porovnání s TomTomem byla hlasová navigace přesnější v Benešově při nájezdu na most. iGo naviguje "zabočte mírně vlevo a pak ihned vpravo", kdežto TomTom říká pouze "na konci ulice zahněte doprava", což může být pro řidiče, který se ve městě nevyzná, trochu matoucí. Jednak lze konec mostu za konec ulice považovat jen s velkou dávkou fantazie a také oznámení o prvním mírném zabočení doleva lépe vystihuje to, že při přímé jízdě před  začátkem mostu bychom vjeli do ulice označené značkou zákaz vjezdu. Také v Praze, při mírném odbočování vlevo z ulice U Zdravotního ústavu do ulice Ruská , kde TomTom sveřepě mlčí, i když odbočení doleva při jízdě z opačného směru hlásí, iGo přesně naviguje instrukcí, abychom se drželi na hlavní silnici a odbočili mírně vlevo. TomTom měl zase při hlasové navigaci navrch při nájezdu na dálnici u Mirošovic směrem na Prahu  - aby mě dostal na "správnou" stranu dálnice (tedy do směru na Prahu a ne na Brno), přikáže před nájezdem na dálnici "nyní se budete držet vlevo", což vám zabrání sjet do pravého pruhu a vydat se směrem do Brna. IGo pouze sdělí, že máte najet na dálnici. Také hlášení TomToma, že se blíží sjezd z dálnice, přichází oproti iGo mnohem dříve. Záleží na rychlosti auta - při rychlosti 130 Km/h TomTom oznamuje poprvé sjezd cca 2 km před samotným sjezdem, zatímco u iGo se musíte spokojit s prvním upozorněním ve vzdáleností cca 500 metrů před sjezdem. Přesto je iGo TomTomovi v kvalitě hlasové navigace dobrou konkurencí a v leckterých složitějších dopravních situacích ho i předčí. Za špičku hlasové navigace považuji stále Dynavix  - i v centru Prahy to byla opravdu jediná navigace, která mě dokázala spolehlivě vést jen hlasovými instrukcemi. TomToma i iGO bych dal při hodnocení kvality hlasové navigace společně na druhé místo ihned za Dynavix.

Grafika iGO je vynikající a při prvním pohledu TomToma předčí. Vlaječky označující počátek a konec trasy jsou krásně animované, názvy ulic ve městech perfektně čitelné a vždy české a ne ceske.  Přesto se neorientuji v 2D ani 3D pohledu tak dobře jako u TomToma, ale to může být dáno tím, že iGo používám zatím velmi krátkou dobu. Schéma následujícího manévru v levé části obrazovky a automatický zoom při příjezdu na křižovatku jsou zpracovány dobře a pokud nemáte s čím srovnávat, budete zcela spokojeni. 

Mapové podklady pro Českou republiku mají oba programy od společnosti TeleAtlas a jejich podrobnost je skvělá. U iGo ale nemáte takové množství POI, které existují pro TomToma. Nepříjemně mě překvapilo, že v obchodních centrech zcela absentuje třeba Hypernova Průhonice. Také zamrzí, že nemůžete z nejbližších POI vyfiltrovat jen ty, které leží přímo na trase.

Ovládání menu iGo "jedním prstem" sice možné je, ale při přímém srovnání s ergonomií ovládání TomToma jsou patrné zásadní nedostatky a nedomyšlenosti. Do dalších úrovní menu se dostáváte složitě a také mi moc nevyhovuje, že při hledání místa je nejdříve zobrazen formulář pro vyhledání ulic ve městě, které jste zadali při posledním hledání. Teprve po volbě změnit město se zobrazí města hledaná dříve a když chcete zadat město, které není v historii hledaných měst, musíte volbou 'Jiné město' přejít na obrazovku, kde zadáte několik počátečních písmen z názvu města. Program iGO na formuláři pro zadání názvu města ukazuje jen počet měst vyhovujících zadávaným písmenům, ale samotná města uvidíte až po stisknutí tlačítka Hotovo. Celý postup mi přijde nesmyslně zdlouhavý a krkolomný. Navíc mi tlačítka softwarové  klávesnice připadají příliš titěrná a to i po jejich zvětšení stisknutím tlačítka Klávesy.

Také první a graficky netradiční rozcestník hlavního menu volbou barev a písma nechtěně vizuálně potlačuje centrální a nejdůležitější položku menu s názvem "Vyhledat a jet". Co naopak u iGo chválím je plánování složitějších cest přes více míst ("lomových bodů"). 

V ergonomii ovládání TomTom jasně vítězí a iGo bude muset hodně zapracovat na odstranění zmíněných nedostatků.

Závěrečné postřehy:

  • U iGo stejně jako u TomToma bych vyzdvihl bezproblémovou konfiguraci a práci s GPS. (BT GPS Holux 230 - spárována s MDA Vario). 
  • Program s celou mapou Evropy se vejde na jednu 1GB SD kartu. Program iGo se prodává na SD kartě a k jeho instalaci dojde po zasunutí SD karty do slotu. Jak asi tušíte, na kartě je adresář s "wellknown" názvem 2577, ze kterého Windows Mobile po zasunutí karty vždy automaticky spustí  soubor nazvaný autorun.exe.
  • Zadání zeměpisných souřadnic.
  • Upozornění na překročení zadané rychlosti.
  • ""Ladění" algoritmu pro výpočet trasy - volba mezi nejrychlejší, nejkratší a ekonomickou trasou. "Profily" trasy pro vozidla, kola, chodce. Možnost zakázat dálnice nebo jen placené dálnice a také třeba nezpevněné cesty.
  • Zakázání obratů do protisměru. Tato funkce ale podle mě nefunguje správně - i když jsem obraty do protisměru zakázal, přesto po mě iGo párkrát při odchýlení se od stanovené trasy obrat do protisměru vyžadoval.
  • Možnost zakázat při výpočtu vnitrostátní trasy cestu přes hranice s okolními státy.
  • Automatické přepínání mezi denním a nočním barevným profilem.

Obrázková galerie iGo:

Rychlý přístup k některým položkám menu   Hlavní menu  Menu v mapě  Režim navigace  Seznam POI  Body zájmu (POI) - kina   Nastavení parametrů trasy   Mapa  - ulice Vinohradská, Praha

Thursday, 11 May 2006 15:41:31 (Central Europe Standard Time, UTC+01:00)       
Comments [3]  Mobilitky | Navigace


 Monday, 01 May 2006
Odstranění problému(ů) s instalací Compact .NET Frameworku 2.0 na Windows Mobile 5.0

Již několikrát jsem se setkal s tím, že na zařízení s Windows Mobile 5.0 byl problém nainstalovat Compact .Net Framework. Pár lidí si mi teď v poslední době v mailu nebo na ICQ také stěžovalo, že jim CNF nejde nainstalovat a že při pátrání po příčinách potíží dostanou nanejvýš jen hlášku, že došlo k problému a že by bylo dobré resetovat zařízení a zkusit instalaci znovu. ;-) Tomu říkám skvělé design guidelines v praxi - "nikdy neobtěžujte uživatele zbytečnými technickými podrobnostmi". :-D

Odstranění problému není složité - z důvodu známému asi jen vývojářskému týmu CNF v Microsoftu a mystérióznímu pro běžného smrtelníka ActiveSync při instalaci CNF z počítače přes Application Manager zkopíruje do zařízení soubor nazvaný NETCFv2.wce5.armv4i.cab místo správného NETCFv2.wm.armv4i.cab. NETCFv2.wm.armv4i.cab patří na všechna současná zařízení používající procesor s ARM V4 kompatibilní instrukční sadou.

Takže selže-li vám instalace, najděte na počítači soubor NETCFv2.wm.armv4i.cab, a zkopírujte jej "ručně" (v Exploreru nebo třeba v v Total Commanderu s pluginem pro CE zařízení)  do PDA. V PDA pak jen cab soubor spusťte a VŽDY zvolte instalaci CNF do zařízení - instalace na kartu (SD, CF) je sice možná, ale při prvním použití CNF dojde stejně k nakopírování všech knihoven do storage v zařízení.

Pokud máte stále problémy s instalací:

  1. Resetujte (soft-reset) zařízení a zkuste nainstalovat CNF znovu. Teď už má reset smysl. ;-)
  2. Nezabere-li ani to, vypněte po dobu instalace všechny Today pluginy, restartujte (soft reset) a znovu instalujte.

Přinejhorším bod 2 zabere podle mých zkušeností vždy - ještě se mi nestalo, že bych na nějaké PDA s WM 5 CNF 2 nenainstaloval ;-)

 



Monday, 01 May 2006 21:50:26 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Compact .Net Framework | Mobilitky