\


 Saturday, 07 July 2007
Net Monitor verze 0.4.0.0

Hlavní změny ve verzi 0.4.0.0
1) Reinicializace RILu po opakovaném spuštění logování.
2) Přidán dialog o aplikaci.
3) Při stahování databází  program využije buď stávající připojení k internetu, nebo při neexistenci připojení se pokusí PDA připojit (přes GPRS, CSD  - dle nakonfigurovaných připojení)
4) Kolem "akčních" ikon vykreslováno ohraničení.

Více informací o Net Monitoru.



Saturday, 07 July 2007 17:15:35 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Mobilitky | Net Monitor


Funkce "AutoConnect" mezi MDA (Pocket PC Phone Editon s MS BT stackem) a autorádiem Pioneer (DEH-P 55 BT) s bluetooth handsfree

Někdy na konci minulého roku jsem si koupil autorádio Pioneer DEH-P 55 BT a i když jsem byl velmi spokojen s kvalitou hovorů, nelíbilo se mi, že s MDA Variem nebo s HTC Artemis (obecně tedy s jakýmkoliv Pocket PC Phone Edition s BT stackem od Microsoftu) není funkční automatické připojení zařízení k rádiu. Jinými slovy - chtěl jsem přijít do auta, otočit klíčkem v zapalování a být si jistý, že všechny hovory budu přijímat přes autorádio. To ale nešlo - musel jsem vždy nastartovat a teprve poté na rádiu ručně zvolit "Connect". Docela opruz.  Naštěstí jsem ale čirou náhodou zjistil, že když v MDA po BT spárování zaškrtnete u autorádia volbu "Set As Handsfree", tak MDA , když je v dosahu rádia a přijmete hovor nebo někomu zavoláte sami, se k rádiu připojí a všechny zvukové vstupy a výstupy telefonní části na něj přesměruje. "Čiré náhodě" dá člověk šanci tak, že když ho přestane bavit otravné hledání položky Connect v menu po každé zastávce v autě a často na tento svého druhu pozoruhodný opičí úkon pozapomene, tak při příchozím hovoru najednou s údivem zjistí, že i bez jeho asistence BT HF stejně funguje. Takže nakonec spokojenost, sice z nečekané strany, ale přesto spokojenost se spoluprací rádia a MDA.

Vrtala mi ale hlavou i další nepříjemnost - rádio MDA při párování nikdy nenašlo. Obezlička (česky Workaround ;-) ): Otevřete BT připojení z rádia (Connect Open - modrá dioda na rádiu začne blikat) a z MDA iniciujete párování.

Přesto mně nedalo spát, proč nelze párovat Vario/Artemis s rádiem stejně jako další telefony a z jakého - čertovským marketingem říznutého - důvodu má rádio nepoužitelnou funkci AutoConnect, který je přitom barvitě a neodolatelně popsána v manuálu - a zde je řešení celé záhady.

MDA se identifikují při BT připojení jako zařízení třídy PDA. Při připojení MDA přes BT k počítači si můžete všimnout přiřazené ikony se symbolem PDA. Rádio ale spolupracuje jen zařízeními třídy 'Phone' nebo 'Smartphone'.

V registrech, v klíči HKLM\SOFTWARE\Microsoft\Bluetooth\sys\COD,  změňte stávající hodnotu na hodnotu 5374476 (decimálně). Tím docílíte toho, že MDA skryje svou pravou identitu a nabídne janusovskou tvář  - místo plnokrevného PDA charakteru poskytne BT rádiem vstřícně očekávané a jemu milé mimikry zdegenerovaných a zkriplovaných SmartPhonů. ;)

Restartujte zařízení a nyní můžete MDA spárovat s rádiem, využít funkce AutoConnect apod.



Saturday, 07 July 2007 14:52:56 (Central Europe Standard Time, UTC+01:00)       
Comments [1]  Mobilitky


 Monday, 02 July 2007
Alfa verze Net monitoru pro Pocket PC ke stažení

Download: http://blog.renestein.net/__DOWNLOAD/NetMonitorTodayInstall.CAB

Sice mám teď nařízen nucený odpočinek, ale ještě předtím se mi podařilo vytvořit Net Monitor pro Pocket PC Phone Edition. Pokud jste nikdy nelovili BTS, ani si nedovedete představit, o jakou zábavu jste přišli. Na starších Nokiích nebo Siemensu S55 bylo jednoduché aktivovat tzv. Net Monitor - režim, ve kterém jsou zobrazovány základní parametry GSM připojení (Cell Id, LAC, Network ID). Net Monitor jsem vytvořil i pro Pocket PC a navic je nyní integrován se skvělými databázemi BTS na GSM webu:

Charakteristika aplikace:

1) Jedna se o Today plugin (udaje se zobrazuji na obrazovce dnes).
2) Aplikace se prozatim snazi zjistit udaje Cell Id, LAC, Network Id  a BCCH. Na HTC Artemis a MDA Variu mam overeno, ze se zobrazi spravne udaje Cell Id a LAC, BCCH se pokusim zjistit jeste jinak. Overeno, ze udaje Cell Id a LAC se zobrazi i na Ipaqu 6340 s WM 2003, HTC TYTN, HTC Trinity, MIU A701 ...

3) Udaje o GSM siti jsou po zapnuti zjistovany dle hodnoty zadane v konfiguracnim dialogu.

3) Aplikace volitelne loguje zjistene udaje do zadaneho souboru) - soubor ma format (Datum); (cas);(LAC);(Cell Id);(BCCH); .
Instalace:
Protoze se jedna o AlFA preview, doporucuji pred instalaci Net Monitoru mit v zarizeni napr. SPB Pocket Plus a v nem aktivovany safe boot - jestlize by vam vytuhlo zarizeni, nebudete nucet delat HR (Hard reset), protoze muzete pri startu zarizeni docasne deaktivovat Today pluginy.

1) Z adresy http://blog.renestein.net/__DOWNLOAD/NetMonitorTodayInstall.CAB si stahnete instalacni CAB.
2) CAB zkopirujte do PDA, spustte jej  a potvrdte pripadne hlasky zabezpeceni.
3) Resetujte (Soft reset) zarizeni - na Today obrazovce se Vam zobrazi novy plugin s hlasenim "Prozatim nebyly zadany zadne udaje". Plugin obsahuje kontextove menu - v nem zvolte polozku Sledovat informace o GSm siti (nebo kliknete na ikonu po leve strane panelu).
Chcete-li udaje logovat, takze zvolte po opakovanem otevreni menu polozku Zapisovat informace do souboru.

V planu je krome veci zminenych vyse:
1) Zapis GPS souradnic ke kazdemu zaznamu v logovacim souboru.
2) Integrace s databazi BTS na GSMWEB.cz.  Online integrace s databázemi BTS na GSMWebu.
3) Graficka indikace primo v pluginu, zda je zapnuto sledovani udaju, zda dochazi k logovani do souboru atd.


Hlavni zmeny ve verzi 0.3.0.0: (Verze 0.2.0.0. nebyla veřejná).

1) Uzivatelske rozhrani Net pluginu zobrazuje udaje v zalozkach.
2) "Offline integrace s databazi GSMWEBU - program dokaze stahnout csv soubory z GSMWebu a na zalozce Podrobnosti zobrazuje podrobne informace o prave nalezene bunce. Konfiguraci csv databazi naleznete v nastaveni (kontextove menu -> nastaveni) - prednastaveny jsou url pro GSM sit TMO, Vodafone a O2. Zmente adresar, do ktereho budou csv soubory ulozeny, pripojte se k internetu (v PRISTI verzi vas program pripoji sam) a kliknete na tlacitko Stahnout vse. Na zalozce podrobnosti se obcas muzete setkat s tim, ze pod udajem LAT se objevi jmeno cloveka, ktery BTS zaevidoval - jde o chybu/nedokonalost stavajicich souboru a ve spolupraci s autory GSM webu se ji pokusim vyresit.
3) Zobrazovani petimistneho Network Id.
4) Zobrazovani sily signalu.
5) Po leve strane je "toolbar" s ikonami pro nejcastejsi akce. Dole je stavovy pruh s ikonami - v soucasne dobe je indikovano zapnuti/vypnuti radiove casti. Zatim se moc nedivejte na ikonky, ty jsou priserne.
6) Opravy chyb a mnoho drobnych vylepseni.

Hlavni zmeny ve verzi 0.1.0.0:

1) Udaje jsou na Today obrazovce zobrazeny v decimalnim formatu (predtim byly v hexa formatu).
2) V logovacim souboru je na kazdem radku i datum.
3) Pokud se misto platneho udaje na today obraozvce zobrazi -1, znamena to, ze pro tento udaj jsem nedostal validni odpoved.
4) Pridan konfiguracni dialog - dostupny z kontextoveho menu pluginu pres polozku Nastaveni nebo primo v nastaveni Today pluginu pres standardni volbu Options.

 

Monday, 02 July 2007 20:07:26 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Mobilitky | Net Monitor


 Wednesday, 27 June 2007
Pozvánka na podzimní běh kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací

Chci vás pozvat na podzimní termíny kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací.

Termíny:

24. - 26. 9. 2007
5. - 7. 11. 2007

Organizační informace ke kurzu

Program kurzu

Zaregistrované ohlasy na školení :

http://blog.renestein.net/ct.ashx?id=10d7acf8-1026-43fe-b1f1-54fccb69105b&url=http%3a%2f%2fwww.jirifabian.net%2fwordpress%2f%3fp%3d157

http://blog.renestein.net/ct.ashx?id=10d7acf8-1026-43fe-b1f1-54fccb69105b&url=http%3a%2f%2fwww.rarous.net%2fclanek%2f143-skoleni-oop-uml-a-navrhovych-vzoru.aspx

 

Omlouvám se za tento přízračně mrtvolný klid na blogu, ale kvůli neočekávaným osobním problémům nemám na blog vůbec čas. Do konce září (alespoň doufám) ale konečně změním kompletně blogovací systém a nasadím slibované wiki + fórum o  OOP a návrhových vzorech.



Wednesday, 27 June 2007 09:38:11 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Kurzy UML a OOP | Návrhové vzory | UML


 Monday, 12 February 2007
Pozvánka na další běh kurzu "Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací" a pár informací navíc

Chci vás pozvat na další termíny kurzu Objektovými principy a návrhovými vzory řízený design a vývoj kvalitních aplikací.

Termíny:

18.04. - 20.04. 2007
02.05. - 04.05. 2007

Organizační informace ke kurzu

Program kurzu

Zaregistrované ohlasy na školení :

http://www.jirifabian.net/wordpress/?p=157

http://www.rarous.net/clanek/143-skoleni-oop-uml-a-navrhovych-vzoru.aspx

 

A malá poznámka pro ty, co si mysleli, že tento blog je již trpí zhoubným zombie syndromem viru dgx  (metlou lidstva dnešních dnů je pro mě nesvatá trojice TBC, HIV, DGX s faktorem RH v komentářích) :-) a čeká se jen na poslední R.I.P. spot  - blog mrtvý není a nebude, jen poslední 3 měsíce na žádné "hobby" libůstky jako je blog nebyl a není stále čas (většinou tato věta představuje trapně křiklavé mimikry lenosti autora blogu, ale u mě jde nyní o empirický a subjektivně drasticky verifikovaný fakt) :-), takže toto období považujte za zimní spánek. V březnu opět začnu publikovat, blog přejde na můj redakční systém (konec DasBlogu a konec jeho rozmarům) a také se objeví slibované fórum od OOP, UML, DSL a návrhových vzorech. Současně s fórem bude spuštěna WIKI na stejná témata - ta již obsahuje několik desítek textů, které jsem stihl napsat ještě minulý rok na podzim.



Monday, 12 February 2007 18:50:49 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Kurzy UML a OOP | Ostatní


 Sunday, 29 October 2006
Analytická hádanka - žhnoucí vztahy mezi třídami
Hádanka

Slovo "žhnoucí" v nadpisu spotu není zavedením dlouho očekávané extenze do UML pro označení libidinózního vztahu mezi třídami :-D, ale jen a pouze hodnotí vztahy, které jsou kvalitními kandidáty na epicentra pořádného požáru, v němž veškeré výhody OOP návrhu jsou devótně obětovány božstvu "najděte v aplikaci podstatná jména, nasekejte z nich třídy a pak si dejte panáka na další úspěch". ;-)

Diagram je záměrně neúplný, takže bych chtěl slyšet, jak by se dal upravit/rozvinout a jaké předpoklady jsou v něm obsaženy.

 

diagram tříd - hádanka na vztahy

 

 

zatím jde jen o triviální problém, ale na subtilnější kličky narazíme brzy v dalších hádankách :)

 



Sunday, 29 October 2006 22:41:37 (Central Europe Standard Time, UTC+01:00)       
Comments [23]  


Kontrola duplicitního spuštění aplikace v Compact .Net Frameworku - Windows CE

I když samotný Compact .Net Framework v souladu s doporučeními Microsoftu pro vývoj Windows Mobile aplikací zajišťuje, že je vždy spuštěna nanejvýš jedna instance aplikace, v Compact .Net Frameworku spuštěném na "čistých" Windows CE již zmíněné pravidlo neplatí a kontrolu na opakované spuštění aplikace musíme doplnit sami.

Tento kód funguje pro Compact .Net Framework od verze 1.x a byl otestován na Windows CE 4.2 a vyšších.

private const int ERROR_ALREADY_EXISTS = 183;

[DllImport("CoreDll.dll")]
private static extern int GetLastError(); 

[DllImport("CoreDll.dll", EntryPoint="CreateMutexW")]

private static extern int CreateMutex( IntPtr
lpMutexAttributes, bool InitialOwner, string MutexName );

public static bool AppAlreadyStarted() 
{ 
string myID =
System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

if( CreateMutex(IntPtr.Zero, true, myID) != 0 )
{
    return (GetLastError() == ERROR_ALREADY_EXISTS);
} 

return false; 
}

Můžeme také najít formulář již spuštěné aplikace podle titulku, přenést jej do popředí a duplicitní instanci aplikace ukončit.

namespace DeviceApplication1
{
static class Program
{
[DllImport("coredll", EntryPoint="FindWindow")] 
private static extern IntPtr FindWindow( 
string lpClassName, 
string lpWindowName); 


[DllImport("coredll", EntryPoint="SetForegroundWindow")] 
private static extern bool SetForegroundWindow(IntPtr hWnd); 

[MTAThread]
static void Main()
{


IntPtr mainWindowHwnd = FindWindow(null, "DeviceMain");


if (mainWindowHwnd.Equals(IntPtr.Zero)) 
{ 
   Application.Run(new Form1()); 
} 
else 
{
   SetForegroundWindow(mainWindowHwnd); 
   Application.Exit(); 
} 

}

}


Sunday, 29 October 2006 20:52:11 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  Compact .Net Framework


 Monday, 09 October 2006
ASP.NET - jednoduchý přístup z kódu na webovém formuláři k prvkům deklarovaným v šabloně
.Net Framework V ASP.NET 1.x jsme při přístupu k prvkům v šabloně (šablonou rozumíme vlastnost serverového ovládacího prvku typu ITemplate) museli zavolat metodu FindControl a předat ji Id hledaného prvku. A protože návratovou hodnotou metody FindControl je pouze rozhraní třídy Control, byli jsme nuceni přetypovávat na odvozený ovládací prvek.
  Label lblMess = LoginControl1.FindControl("lblMessage") as Label;

U prvků DataList, Repeater a dalších, kteří používají šablony pro opakování stejného obsahu pro každý řádek v datovém zdroji (ItemTemplate, AlternateItemTemplate) je použití metody FindControl odůvodněné. Ovládací prvky v šabloně jsou vytvořeny opakovaně pro všechny řádky v datovém zdroji a rodičovský prvek šablony implementací rozhraní INamingContainer zajišťuje, že každá instance šablony je v html formuláři složena z html elementů s unikátními hierarchickými názvy. Metoda FindControl na řádku  Datalistu, Repeateru si můžeme zjednodušeně představit jako "překladač" dlouhého, hierarchického a automaticky generovaného Id na jednoduché Id zadané v šabloně. Vidíme-li na stránce Id LoginControl1_ctl00_lblMessage, můžeme se k prvku s Id 'lblMessage' dostat tak, jak jsme si ukázali v kódu výše.

Proč si ale komplikovat život, když máme na stránce vždy maximálně jednu instanci šablony? Šablona prvku WizardStep bude na stránce právě jednou, protože šablonu jednoho kroku v průvodci (asp:wizard) nepoužíváme pro opakovanou instanciaci stejného obsahu, ale jen pro vytvoření vlastního vzhledu jednoho kroku průvodce. Šablonu nám prvek wizard nabízí jen proto, abychom si mohli vytvořit pěkné vlastní uživatelské rozhraní a nebyli sešněrováni ve svém tvůrčím rozletu představami ASP.NET týmu. Pak ale není žádný důvod, abychom k prvkům šablony přistupovali přes metodu FindControl. Prvky jsou na stránce pouze jednou a je bezpečné na ně odkazovat přímo na úrovni stránky jako na každý jiný ovládací prvek v ASP.NET formuláři, protože nehrozí kolize jejich Id.

ASP.NET 2.0 dovoluje u každé vlastnosti typu ITemplate určit, jestli bude šablona instanciována na jedné stránce opakovaně, anebo zda se na šablona stránce vyskytne nanejvýš jednou. Informaci o tom, jak budete šablonu používat, nese nový atribut TemplateInstance, kterým dekorujete vlastnost ITemplate.

 [TemplateInstance(TemplateInstance.Single)]

Hodnotu Single z enumerace TemplateInstance ASP.NET interpretuje jako příkaz k vygenerování typových proměnných na úrovni stránky pro všechny ovládací prvky v šabloně.

Když atribut TemplateInstance nepoužijeme nebo zvolíme režim TemplateInstance.Multiple, k vygenerování proměnných nedojde a ASP.NET 2.0 se k prvkům k šabloně chová stejně jako ASP.NET 1.x.

Zde je jednoduchý serverový ovládací prvek LoginControl, který obsahuje dvě šablony - jednu pro anonymní uživatele a druhou, asi nepřekvapivě,  pro přihlášené uživatele. Obě šablony jsou dekorovány atributem TemplateInstance s hodnotou TemplateInstance.Single - jako autoři ovládacího prvku víme, že určitě nebudeme používat více instancí jedné šablony.

namespace RStein.Web.UI.WebControls
{
    /// <summary>
    /// Serverový ovládací prvek, který dovoluje definovat odlišné šablony pro anonymního a přihlášeného uživatele
    /// </summary>
    [DefaultProperty("AnonymousUserMessage")]
    [DefaultEvent("LoginRequest")]
    [ToolboxData("<{0}:LoginControl runat=server></{0}:LoginControl>")]
    public class LoginControl : CompositeControl
    {
        

        #region Delegates
        public delegate void LoginItemCommandEventHandler (object sender, CommandEventArgs e);
        #endregion Delegates
        #region Public Constants
        /// <summary>
        /// popisek na tlačítko pro událost <see cref="LoginRequest"/>
        /// </summary>
        public const string LOGIN_BUTTON_NAME = "Login";
        
        /// <summary>
        /// Konstanta reprezentuje popisek na tlačítko pro událost <see cref="LogoutRequest"/>
        /// </summary>
        public const string LOGOUT_BUTTON_NAME = "Logout";
        
        #endregion Public Constants

        #region Events Keys

        /// <summary>
        /// Klíč události <see cref="LoginRequest"/>
        /// </summary>
        public static readonly Object LoginRequestKey = new Object();
        
        /// <summary>
        /// Klíč události <see cref="LoginRequest"/>
        /// </summary>
        public static readonly Object LogoutRequestKey = new Object();
        
        /// <summary>
        /// Klíč události <see cref="ItemCommand"/>
        /// </summary>
        public static readonly Object ItemCommandKey = new Object();
        
        #endregion Events Keys
        

        #region Public Events
        /// <summary>
        /// Událost 'Přihlásit uživatele' je vyvolána po kliknutuí na tlačítko s popiskem <see cref="LoginButtonName"/>
        /// </summary>
        public event EventHandler LoginRequest
        {
            add
            {
                Events.AddHandler(LoginRequestKey, value);
            }
            
            remove
            {
                Events.RemoveHandler(LoginRequestKey, value);
            }
        }
        
        /// <summary>
        /// Událost 'Odhlásit  uživatele' je vyvolána po kliknutuí na tlačítko s popiskem <see cref="LogoutButtonName"/>
        /// </summary>
        public event EventHandler LogoutRequest
        {
            add
            {
                Events.AddHandler(LogoutRequestKey, value);
            }
            
            remove
            {
                Events.RemoveHandler(LogoutRequestKey, value);
            }
        }
        
        /// <summary>
        /// Událost zprostředkovává události vnořených ovládacích prvků
        /// </summary>
        public event LoginItemCommandEventHandler ItemCommand
        {
            add
            {
                Events.AddHandler(ItemCommandKey, value);
            }
            
            remove
            {
                Events.RemoveHandler(ItemCommandKey, value);
            }
        }
        
        #endregion Public Events
        
        
        #region Private variables
        private LoginControlContent m_content;
        private ITemplate m_anonymousTemplate;
        private ITemplate m_loggedInTemplate;
        #endregion Private variables
        
        #region Contructors
        /// <summary>
        /// Konstruktor
        /// </summary>
        public LoginControl()
        {

        }
        #endregion Contructors
        
        
        #region Public properties
    
        /// <summary>
        /// Vlastnost dovoluje přistupovat k prvkům šablony přes FindControl
        /// </summary>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public LoginControlContent Content
        {
            get
            {
                EnsureChildControls();
                return m_content;
            }
        }

        /// <summary>
        /// Šablona pro přihlášeného uživatele
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(LoginControlContent))]
        [TemplateInstance(TemplateInstance.Single)]
        public ITemplate LoggedInTemplate
        {
            get
            {
                return m_loggedInTemplate;
            }

            set
            {
                m_loggedInTemplate = value;
            }
        }

        /// <summary>
        /// Šablona pro nepřihlášeného uživatele
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [TemplateContainer(typeof(LoginControlContent))]
        [TemplateInstance(TemplateInstance.Single)]
        public ITemplate AnonymousTemplate
        {
            get
            {
                return m_anonymousTemplate;
            }

            set
            {
                m_anonymousTemplate = value;
            }
        }
        
        /// <summary>
        /// Informace zobrazená nepřihlášenému uživateli
        /// </summary>
        [Category("Behavior")]
        [Bindable(true)]
        [DefaultValue("")]
        [Description("Informace zobrazená nepřihlášenému uživateli")]
        public string AnonymousUserMessage
        {
            get
            {
                string message = (string) ViewState["AnonymousUserMessage"];
                return (message == null ? String.Empty : message);
            }
            
            set
            {
                ViewState["AnonymousUserMessage"] = value;
            }
        }

        /// <summary>
        /// Informace zobrazená přihlášenému uživateli
        /// </summary>
        [Category("Behavior")]
        [Bindable(true)]
        [DefaultValue("")]
        [Description("Informace zobrazená přihlášenému uživateli")]
        public string LoggedInMessage
        {
            get
            {
                string message = (string) ViewState["LoggedInMessage"];
                return (message == null ? String.Empty : message);
            }
            set
            {
                ViewState["LoggedInMessage"] = value;
            }
        }
        #endregion Public properties        
        
        #region Protected properties        
        
        /// <summary>
        /// Prvek bude uzavřen v HTML značce DIV
        /// </summary>
        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }

        #endregion Protected properties        

        #region Protected methods
        
    
        /// <summary>
        /// Vytvoření vnořených ovládacích prvků
        /// </summary>
        protected override void CreateChildControls()
        {
            
            Controls.Clear();
            
            if (Page.User.Identity.IsAuthenticated)
            {
                m_content = new LoginControlContent(Page.User.Identity.Name, AnonymousUserMessage, LoggedInMessage);
                ITemplate template = null;

                if (m_loggedInTemplate != null)
                {
                    template = m_loggedInTemplate;
                }
                else
                {
                    template = new DefaultLoggedInTemplate();
                }
                
                template.InstantiateIn(m_content);
                
            }
            else
            {
                m_content = new LoginControlContent(String.Empty, AnonymousUserMessage, LoggedInMessage);
                
                ITemplate template = null;
                
                if (m_anonymousTemplate != null)
                {
                    template = m_anonymousTemplate;
                }
                else
                {
                    template = new DefaultAnonymousTemplate();
                }
                
                template.InstantiateIn(m_content);
                    
                
            }
            
            this.Controls.Add(m_content);
            
        }

        /// <summary>
        /// Přpsání metody, která zachycuje bublané události
        /// </summary>
        /// <param name="source">Zdroj bublané události</param>
        /// <param name="args">Argumenty bublané události</param>
        /// <returns><see cref="true"/> - Událost byla zpracována, <see cref="false"/> - Událost nebyla zpracována</returns>
        protected override bool OnBubbleEvent(object source, EventArgs e)
        {
            CommandEventArgs ex = e as CommandEventArgs;
            if (ex != null)
            {
                if (ex.CommandName.ToLower() == LOGIN_BUTTON_NAME.ToLower())
                {
                    OnLoginRequest(new EventArgs());
                }

                else if (ex.CommandName.ToLower() == LOGOUT_BUTTON_NAME.ToLower())
                {
                    OnLogoutRequest(new EventArgs());
                }

                else
                {
                    OnItemCommand(ex);
                }
                
                return true;
            }
            
            return false;
        }

        /// <summary>
        /// Metoda odpovědná za vyvolání události loginRequest
        /// </summary>
        /// <param name="e">Parametry události</param>
        protected virtual void OnLoginRequest(EventArgs e)
        {
            EventHandler eh = (EventHandler) Events[LoginRequestKey];
            if (eh != null)
            {
                eh(this, e);
            }
        }

        /// <summary>
        /// Metoda odpovědná za vyvolání události LogoutRequest
        /// </summary>
        /// <param name="e">Parametry události</param>
        protected virtual void OnLogoutRequest(EventArgs e)
        {
            EventHandler eh = (EventHandler) Events[LogoutRequestKey];

            if (eh != null)
            {
                eh(this, e);
            }
        }

        /// <summary>
        /// Metoda odpovědná za vyvolání události ItemCommand
        /// </summary>
        /// <param name="e">Parametry události</param>
        protected virtual void OnItemCommand(CommandEventArgs e)
        {
            LoginItemCommandEventHandler eh = (LoginItemCommandEventHandler) Events[ItemCommandKey];
           
            if (eh != null)
            {
                eh(this, e);
            }
        }

        #endregion Protected methods
    }
}

LoginControl použijeme na testovací stránce a zadáme anonymní šablonu.

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Assembly="WebControlLibrary1" Namespace="RStein.Web.UI.WebControls"
    TagPrefix="cc2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Testovací stránka</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <cc2:LoginControl ID="LoginControl1" runat="server" AnonymousUserMessage="Přihlašte se prosím" OnLoginRequest="LoginControl1_LoginRequest">
            <AnonymousTemplate>
                <asp:label runat="server" ID="lblMessage"><%#Container.AnonymousMessage%> </asp:label> <br />
                <asp:LinkButton Id="Login" runat="server" Text="Přihlásit se" />                          
            </AnonymousTemplate>
        </cc2:LoginControl>
        <
    </div>
    </form>
</body>
</html>

Tlačítko Login i popisek lblMessage deklarované v šabloně jsou přímo dostupné ze stránky, jak si můžeme ověřit, když v události PreRender stránky změníme barvu pozadí popisku lblMessage. Nemusíme používat metodu FindControl, ani přetypovávat, což jsou docela příjemná vylepšení kódu ;)

 private void Page_PreRender(object sender, EventArgs e)
    {
        LoginControl1.DataBind();

        if (lblMessage != null)
        {
            lblMessage.BackColor = Color.Cyan;
        }
    }

 

Abyste mohli ovládací prvek LoginControl zkompilovat, následuje kód používaných pomocných tříd.

using System;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;

namespace RStein.Web.UI.WebControls
{
    /// <summary>
    /// Kontejner pro šablony
    /// </summary>
    [ToolboxItem(false)]
    public class LoginControlContent : Control, INamingContainer
    {
        #region Private variables
        private string m_userName;
        private string m_anonymousMessage;
        private string m_loggedInMessage;
        #endregion Private variables
        /// <summary>
        /// Konstruktor
        /// </summary>
        /// <param name="userName">Jméno uživatele</param>
        /// <param name="anonymousMessage">Zpráva pro nepřihlášeného uživatele</param>
        /// <param name="loggedInMessage">Zpráva pro přihlášeného uživatele</param>
        internal LoginControlContent(string userName, string anonymousMessage, string loggedInMessage)
        {
            m_userName = userName;
            m_anonymousMessage = anonymousMessage;
            m_loggedInMessage = loggedInMessage;
        }
        
        /// <summary>
        /// Jméno uživatele
        /// </summary>
        public string UserName
        {
            get
            {
                return m_userName;
            }
        }

        /// <summary>
        ///Zpráva pro nepřihlášeného uživatele
        /// </summary>
        public string AnonymousMessage
        {
            get
            {
                return m_anonymousMessage;
            }
        }

        /// <summary>
        ///Zpráva pro přihlášeného uživatele
        /// </summary>
        public string LoggedInMessage
        {
            get
            {
                return m_loggedInMessage;
            }
        }
    }
}

using System;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace RStein.Web.UI.WebControls
{
    /// <summary>
    /// Standardní šablona pro nepřihlášeného uživatele
    /// </summary>
    public class DefaultAnonymousTemplate : ITemplate
    {
        #region Constructors
        /// <summary>
        /// Konstruktor
        /// </summary>
        internal DefaultAnonymousTemplate()
        {
        }
        #endregion Constructors

        #region public methods
        #region ITemplate Members
        /// <summary>
        /// Implementace InstantiateIn - vytvoření ovládacích prvků anonymní šablony
        /// </summary>
        /// <param name="container">Ovládací prvek, do jehož kolekce Controls bzdou prvky šablony přidány</param>
        public void InstantiateIn(Control container)
        {
            Label lblMessage = new Label();
            lblMessage.ID = "lblMessage";
            lblMessage.DataBinding += new EventHandler(lblMesssage_DataBind);
            
            LiteralControl separator = new LiteralControl("&nbsp;");
            
            LinkButton btnLogin = new LinkButton();
            btnLogin.ID = "btnLogin";
            btnLogin.Text = "Přihlásit";
            btnLogin.CommandName = LoginControl.LOGIN_BUTTON_NAME;

            container.Controls.Add(lblMessage);
            container.Controls.Add(separator);
            container.Controls.Add(btnLogin);


        }

        #endregion ITemplate Members
        #endregion public methods
        
        #region private methods
        //Handler události DataBind prvku lblMessage
        private void lblMesssage_DataBind(object sender, EventArgs e)
        {
            Label lblMessage = (Label) sender;
            LoginControlContent currContent = lblMessage.NamingContainer as LoginControlContent;
            lblMessage.Text = currContent.AnonymousMessage;
        }
        #endregion private methods
    }
}

using System;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace RStein.Web.UI.WebControls
{
    /// <summary>
    /// Standardní šablona pro přihlášeného uživatele
    /// </summary>
    public class DefaultLoggedInTemplate : ITemplate
    {
        #region constructors
        /// <summary>
        /// Konstruktor
        /// </summary>
        internal DefaultLoggedInTemplate()
        {
        }
        #endregion constructors

        #region public methods
        #region ITemplate Members
        /// <summary>
        /// Implementace InstantiateIn - vytvoření ovládacích prvků anonymní šablony
        /// </summary>
        /// <param name="container">Ovládací prvek, do jehož kolekce Controls bzdou prvky šablony přidány</param>
        public void InstantiateIn(Control container)
        {
            Label lblMessage = new Label();
            lblMessage.ID = "lblMessage";
            lblMessage.DataBinding += new EventHandler(lblMesssage_DataBind);
            
            LiteralControl separator = new LiteralControl("&nbsp;");
            
            LinkButton btnLogout = new LinkButton();
            btnLogout.ID = "btnLogout";
            btnLogout.Text = "Odhlásit";
            btnLogout.CommandName = LoginControl.LOGOUT_BUTTON_NAME;

            container.Controls.Add(lblMessage);
            container.Controls.Add(separator);
            container.Controls.Add(btnLogout);


        }

        #endregion ITemplate Members
        #endregion public methods
        
        #region private methods
        //Handler události DataBind prvku lblMessage
        private void lblMesssage_DataBind(object sender, EventArgs e)
        {
            Label lblMessage = (Label) sender;
            LoginControlContent currContent = lblMessage.NamingContainer as LoginControlContent;
            lblMessage.Text = currContent.LoggedInMessage + " " + currContent.UserName;
        }
        #endregion private methods
    }
}

 



Monday, 09 October 2006 15:42:53 (Central Europe Standard Time, UTC+01:00)       
Comments [2]  .NET Framework | ASP.NET


 Wednesday, 13 September 2006
Windows Forms DataGridView - nevykreslování záhlaví sloupce
.Net Framework

V .Net konferenci na serveru builder se objevil dotaz, jak skrýt záhlaví (header) sloupce v DataGridView. Kolegové, zvyklí pravděpodobně stále na poněkud nehrabaný DataGrid z verze 1.x .Net Frameworku, radili vytvořit nový sloupec a nové záhlaví.

Nejjednodušší řešení ale představuje odchycení události CellPainting DatagridView a a v ní zamezíte vykreslení sloupce nastavením vlastnosti Handled na true. DataGridView má ale mnohem lepší objektový model než DataGrid a jednoduchých změn ve vykreslování DataGridView dosáhneme rychle v obsluze událostí CellPainting, RowPrePaint, RowPostPaint a dalších.

        const int hiddenRowIndex = -1; //záhlaví má index -1
        const int hiddenColumnIndex = 0; //skryjeme první sloupec

        private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.RowIndex == hiddenRowIndex && e.ColumnIndex == hiddenColumnIndex)
            {
                e.Handled = true;
            }
        }

Update : Samozřejmě nemusíte zcela rezignovat na vykreslení buňky a chcete vybarvit alespoň její pozadí.

Opět je to jednoduché - vyplníme pozadí a nastavíme e.Handled na true

e.Graphics.FillRectangle(myColor, e.CellBounds);

e.Handled = true;



Wednesday, 13 September 2006 17:17:52 (Central Europe Standard Time, UTC+01:00)       
Comments [0]  .NET Framework | Windows Forms


 Monday, 11 September 2006
Fórum o OOP, UML, návrhových vzorech, MDA, DSL ... - chtěli byste?

Nadpis vyjadřuje v kostce vše. Hraji si právě teď s překladem a nastavením YetAnotherForum a napadlo mě, že bych na doméně forum.renestein.net spustil fórum, kde bychom společně diskutovali o návrhu aplikací, systémovém designu, OOP, UML, Model Driven Architecture, DSL, zuřivě bychom se hádali nad best practices, vášnivě "flamovali" nad podporou OOP v různých programovacích jazycích :) nebo bychom si vyměňovali linky na zajímavé články. Pro každé větší téma by existovalo samostatné fórum.

Vím. že některá česká fóra se OOP a analýzou zabývají, ale kvůli svému neodvolatelně  finálním stavu  "mrtvé" fórum s občasnými "self" přechody, spuštěnými přijetím jedné OT zprávy s nabídkou domácích zásob viagry nějakého momentálně insolventního a celoživotně impotentního spammera, se v nich nic zajímavého neděje.

Takže - máte zájem? :) 



Monday, 11 September 2006 14:55:02 (Central Europe Standard Time, UTC+01:00)       
Comments [19]  Návrhové vzory | Ostatní | UML