<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>René Stein - Compact .Net Framework</title>
    <link>http://blog.renestein.net/</link>
    <description>Názory vzešlé z mesaliance humanitní skepse a technologického optimismu</description>
    <image>
      <url>http://blog.renestein.net/themes/discreetBlogBlue/SpotImages/sfinga_rss.jpg</url>
      <title>René Stein - Compact .Net Framework</title>
      <link>http://blog.renestein.net/</link>
    </image>
    <language>cs-CZ</language>
    <copyright>René Stein</copyright>
    <lastBuildDate>Mon, 21 Mar 2011 12:11:41 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.7174.0</generator>
    <managingEditor>rene@renestein.net</managingEditor>
    <webMaster>rene@renestein.net</webMaster>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=7aff293a-4afa-4efa-8bfa-78500f267cfa</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,7aff293a-4afa-4efa-8bfa-78500f267cfa.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,7aff293a-4afa-4efa-8bfa-78500f267cfa.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=7aff293a-4afa-4efa-8bfa-78500f267cfa</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Přibližně před rokem jsem u dvou firem začínal sérii technologických kurzů subjektivním
shrnutím změn (nejen) v aplikacích psaných v .Net Frameworku. Nedávno jsme ji s kolegou
náhodou otevřeli a pobavili jsme se nad tím, jak je rok v IT stále dlouhá doba a že
zde dvojnásobně platí “tempus fugit”. Napadlo mě, že se nad prezentací možná se pobaví
i někdo další, hlavně v pasážích, kde jemně naznačuju zálibu Microsoftu v zařezávání
technologií.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/de5bdc4acd85_ADFB/wlEmoticon-smile_2.png" /></p>
        <p>
U prezentace je třeba mít na paměti:
</p>
        <ol>
          <li>
Jedná se jen o osnovu “přehledové“ a cca dvouhodinové přednášky.<br /><br /></li>
          <li>
Témata, typy projektů a technologie jsou v přednášce voleny podle zájmu zákazníka.<br /><br /></li>
          <li>
Snažil jsem se nebýt hned  v této úvodní přednášce příliš ostrý a konfliktní.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/de5bdc4acd85_ADFB/wlEmoticon-smile_2.png" /><br /><br /></li>
          <li>
Zvolená témata se týkala oblastí, které jsme v dalších dnech probíraly detailněji
na konkrétních projektech vytvořených na návazných kurzech. Po pár zkušenostech si
myslím, že jediný smyslupný kurz zabývající se technologií či programovacím jazykem
je ten, na kterém píšete před účastníky kód. Tato přednáška byla koncipována jako
motivační úvod k dalším tématům.</li>
        </ol>
        <div style="width: 425px" id="__ss_7332936">
          <strong style="margin: 12px 0px 4px; display: block">
            <a title="Moderni trendy ve_vyvoji_aplikaci" href="http://www.slideshare.net/RENESTEIN/moderni-trendy-vevyvojiaplikaci">Moderni
trendy ve_vyvoji_aplikaci</a>
          </strong>
          <object id="__sse7332936" width="425" height="355">
            <param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=modernitrendyvevyvojiaplikaci-110321070156-phpapp01&amp;stripped_title=moderni-trendy-vevyvojiaplikaci&amp;userName=RENESTEIN" />
            <param name="allowFullScreen" value="true" />
            <param name="allowScriptAccess" value="always" />
            <embed name="__sse7332936" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=modernitrendyvevyvojiaplikaci-110321070156-phpapp01&amp;stripped_title=moderni-trendy-vevyvojiaplikaci&amp;userName=RENESTEIN" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355">
            </embed>
          </object>
          <div style="padding-bottom: 12px; padding-left: 0px; padding-right: 0px; padding-top: 5px">View
more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/RENESTEIN">RENESTEIN</a>.
</div>
        </div>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=7aff293a-4afa-4efa-8bfa-78500f267cfa" />
      </body>
      <title>Prezentace Modern&amp;iacute; trendy ve v&amp;yacute;voji aplikac&amp;iacute;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,7aff293a-4afa-4efa-8bfa-78500f267cfa.aspx</guid>
      <link>http://blog.renestein.net/Prezentace+Moderniacute+Trendy+Ve+Vyacutevoji+Aplikaciacute.aspx</link>
      <pubDate>Mon, 21 Mar 2011 12:11:41 GMT</pubDate>
      <description>&lt;p&gt;
Přibližně před rokem jsem u dvou firem začínal sérii technologických kurzů subjektivním
shrnutím změn (nejen) v aplikacích psaných v .Net Frameworku. Nedávno jsme ji s kolegou
náhodou otevřeli a pobavili jsme se nad tím, jak je rok v IT stále dlouhá doba a že
zde dvojnásobně platí “tempus fugit”. Napadlo mě, že se nad prezentací možná se pobaví
i někdo další, hlavně v pasážích, kde jemně naznačuju zálibu Microsoftu v zařezávání
technologií.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/de5bdc4acd85_ADFB/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
U prezentace je třeba mít na paměti:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Jedná se jen o osnovu “přehledové“ a cca dvouhodinové přednášky.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Témata, typy projektů a technologie jsou v přednášce voleny podle zájmu zákazníka.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Snažil jsem se nebýt hned&amp;nbsp; v této úvodní přednášce příliš ostrý a konfliktní.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/de5bdc4acd85_ADFB/wlEmoticon-smile_2.png"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zvolená témata se týkala oblastí, které jsme v dalších dnech probíraly detailněji
na konkrétních projektech vytvořených na návazných kurzech. Po pár zkušenostech si
myslím, že jediný smyslupný kurz zabývající se technologií či programovacím jazykem
je ten, na kterém píšete před účastníky kód. Tato přednáška byla koncipována jako
motivační úvod k dalším tématům.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style="width: 425px" id="__ss_7332936"&gt;&lt;strong style="margin: 12px 0px 4px; display: block"&gt;&lt;a title="Moderni trendy ve_vyvoji_aplikaci" href="http://www.slideshare.net/RENESTEIN/moderni-trendy-vevyvojiaplikaci"&gt;Moderni
trendy ve_vyvoji_aplikaci&lt;/a&gt;&lt;/strong&gt;
&lt;object id="__sse7332936" width="425" height="355"&gt;
&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=modernitrendyvevyvojiaplikaci-110321070156-phpapp01&amp;amp;stripped_title=moderni-trendy-vevyvojiaplikaci&amp;amp;userName=RENESTEIN" /&gt;
&lt;param name="allowFullScreen" value="true" /&gt;
&lt;param name="allowScriptAccess" value="always" /&gt;&lt;embed name="__sse7332936" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=modernitrendyvevyvojiaplikaci-110321070156-phpapp01&amp;amp;stripped_title=moderni-trendy-vevyvojiaplikaci&amp;amp;userName=RENESTEIN" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;
&lt;/object&gt;
&lt;div style="padding-bottom: 12px; padding-left: 0px; padding-right: 0px; padding-top: 5px"&gt;View
more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/RENESTEIN"&gt;RENESTEIN&lt;/a&gt;.
&lt;/div&gt;
&lt;/div&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=7aff293a-4afa-4efa-8bfa-78500f267cfa" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,7aff293a-4afa-4efa-8bfa-78500f267cfa.aspx</comments>
      <category>.NET Framework</category>
      <category>ASP.NET</category>
      <category>C#</category>
      <category>Compact .Net Framework</category>
      <category>LINQ</category>
      <category>RX Extensions</category>
      <category>Silverlight</category>
      <category>Web Services</category>
      <category>Windows Forms</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=be4f9165-3d77-40c8-aea2-e7f8087f9b70</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,be4f9165-3d77-40c8-aea2-e7f8087f9b70.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,be4f9165-3d77-40c8-aea2-e7f8087f9b70.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=be4f9165-3d77-40c8-aea2-e7f8087f9b70</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Na twitteru i v emailu se opakuje stále několik dotazů od lidí, kteří koketují s myšlenkou
pořídit si WP7 telefon nebo chtějí pro WP7 vyvíjet. Účelem tohoto článku není suplovat
uživatelský informační servis o WP7, který u nás skvěle dělá <a href="http://www.smartmania.cz">Smartmania</a> a
kterému se i  v zahraničí  věnuje mnoho webů, ale nabídnout snad trochu
jiné informace než ty, které různí nájemní pisálci stále kopírují z tiskových zpráv
a oficiálních prezentací a které další sociálně-altruističtí trotlové bezmyšlenkovitě
linkují, sdílejí a lajkují.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /></p>
        <p>
          <em>
            <font style="background-color: #00ff00">Je Windows Phone 7 zcela nový operační
systém, který Microsoft skutečně vyvinul  “na zelené louce” a který nemá <strong>NIC</strong> společného
s Windows Mobile?</font>
          </em>
        </p>
        <p>
Je i není.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-winkingsmile_2.png" /> Neuspokojivá
odpověď ve stylu hárající chytré horákyně, já vím. Windows Phone 7 jsou postaveny
na operačním systému Windows CE, na kterém běžely i Windows Mobile. Dnešní oficiální
název zní <a href="http://msdn.microsoft.com/en-us/library/ee483001.aspx">Windows
Embedded CE</a> a aktuální verze má pořadové číslo 6. I Windows Mobile v poslední
verzi 6.5 byly stále založeny na Windows CE 5. Jak vidíte, Microsoft nám to moc neulehčuje
a  číslo verze Windows Mobile není nijak závislé na verzi použitých Windows CE.
WP7 dle všech indicií běží na buildu Windows CE 6.
</p>
        <p>
Windows CE 6 mají oprotí Windows CE 5 několik výhod. A z toho plyne, že i WP7 využívají
nových rysů v systému a netrpí hlavními problémy Windows Mobile aplikací.
</p>
        <ul>
          <li>
Ve Windows CE 5 mohlo běžet najednou maximálně 32 procesů. Ano, celých 32 procesů
musí stačit každému, ale s tím, jak se smartphony/PDA/MDA vyvíjely a výrobci ihned
po startu zařízení obsazovali stále více procesních slotů pro své a se zařízením dodávané
aplikace, se tento limit kupodivu ukázal nedostačující. Podpora cca 32 000 procesů
ve Windows CE 6 je pořádné zlepšení. 
<br /><br /></li>
          <li>
Ve Windows CE 5 měl každý proces 32 MB virtuální paměti a všechny procesy sdílely
4 GB adresní prostor. Nechci zabíhat do detailů, ale způsob nahrávání dynamických
knihoven a jejich sdílení mezi procesy mohl vést velmi rychle k fragmentaci paměti
a k chybě “nedostatek paměti”, i když fyzické paměti bylo dostatek. V CE 6.0 jsou
2 GB virtuálního paměťového prostoru vyhrazeny pro kernel a 2 GB pro každý proces.
Správa paměti v CE 6 má některé nepříjemné dopady na vývojáře kernel/user driverů,
ale pro uživatele i vývojáře aplikací je tento paměťový model mnohem lepší.</li>
        </ul>
        <p>
 
</p>
        <p>
Mobilní Silverlight ve WP7 interně využívá Compact .Net Framework, který můžete znát
z Windows Mobile. Jestliže pro WP7 vyvíjíte, poznáte to i podle toho, že při ladění
aplikace a pokusu editovat zdrový kód vám Visual Studio hlásí, že Compact .Net Framework
aplikace nemohou být při ladění upravovány.
</p>
        <p>
Shrnuto – Windows Phone 7 mají nový kabátek (UI Metro), nová běhová prostředí pro
uživatelské aplikace (Silverlight, XNA Framework) a vylepšený podvozek (CE 6). Psát
a hlavně v článcích zdůrazňovat, že WP7 nemají se staršími Windows Mobile <strong>NIC</strong> společného,
mi přijde v lepším případě naivní, v tom horším okázale neprofesionální. Už minulý
rok jsem psal několikrát , že Microsoft <a href="http://twitter.com/#!/renestein/status/22298585861193730">by
těžko za pár měsíců vyvinul zcela nový mobilní operační systém</a>.
</p>
        <p>
          <em>
            <font style="background-color: #00ff00">Mohu v ČR nakupovat aplikace v  marketplace?</font>
          </em>
        </p>
        <p>
          <font style="background-color: #00ff00">
          </font>Stručná odpověď: Ne. 
</p>
        <p>
Složitější odpověď. Microsoft podle neoficiálních informací uvažuje, že marketplace
v ČR bude dostupný “v létě <strike>2010 </strike>2011”. 
<br />
Neoficiálně to jde – stačí mít zahraniční platební kartu, založit nějaký Live účet,
kde nastavíte, že pocházíte třeba z USA/UK. Ale musíte být asi velcí blázni nebo nadšenci,
abyste si přes tyto obstrukce kupovali dnes (psáno 15.2. 2011) v ČR WP7 telefon. Počítejte
také s tím, že když Microsoft zpřístupní marketplace pro ČR, a vy budete chtít používat
svůj běžný Live účet, zakoupené aplikace mezi různými Live účty nepřevedete.
</p>
        <p>
          <em>
            <font style="background-color: #00ff00">Mohu dnes dát svou WP7 aplikaci do marketplace?</font>
          </em>
        </p>
        <p>
Stručná odpověď: Ne. 
<br />
Složitější odpověď. Pokud chcete dát aplikaci do marketplace, vyvíjejte se zahraničním
partnerem. Je možné také se s trochou kreativity při tvorbě vývojářského účtu (v komentářích
tohle sousloví vysvětlovat raději nebudu<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" />)
registrovat jako vývojář z jiné země, pokud máte zahraniční platební kartu, ale riskujete,
že Microsoft na tento “trik” přijde a zablokuje vám prodej aplikací, protože porušujete
jeho podmínky.
</p>
        <p>
          <font style="background-color: #00ff00">
            <em>Dobře, jsem smířen s tím, že se do market
place prozatím nedostanu, ale přesto chci svou aplikaci otestovat na reálném zařízení,
a ne jen v emulátoru. Jak to udělám, když mi WP7 telefon nedovolí nahrát vlastní aplikace?</em>
          </font>
        </p>
        <p>
          <font style="background-color: #00ff00">
          </font>Nejjednodušší je dnes použít Chevron
WP7 k neoficiálnímu odemknutí telefonu. Poté co telefon odemknete, můžete nahrávat
své vlastní aplikace. <a href="http://forum.xda-developers.com/showthread.php?t=857127">Podrobný
návod, jak odemknout telefon, je na XDA-Developers</a>, takže jej zde nebudu opakovat.
Autoři Chevronu používají na odemčení WP7 telefonu jednoduchý trik. Požadavek na odemčení
telefonu cílený na servery Microsoftu přesměrují na lokální počítač a odemčení telefonu
povolí.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /> Výhodou
je, že nejde o vážný zásah do zařízení, nevýhodou, že pro Microsoft bude snadné tuhle
“díru” (dá se pro tohle amatérské zabezpečení najít nějaký jiný eufemismus?) 
uzavřít další plánovanou aktualizací. Microsoft ale po setkání s autory Chevronu přislíbil,
že sám umožní “co nejdříve” vývojářům nahrání a ladění vlastních aplikací v telefonu,
aniž by bylo nutné otevírat a platit za vývojářský účet. Neznámou proměnnou je, které
jednotky pro měření času používá Microsoft, kde, soudě podle stále odkládaného data
první aktualizace pro WP7, korporátní čas evidentně plyne pomaleji, a jestli optimistická
fráze “co nejdříve” zahrnuje alespoň předpokládanou dobu životnosti WP7 na trhu smartphonů.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /></p>
        <p>
          <font style="background-color: #00ff00">Mohu pro WP7 vyvíjet v Compact .Net Frameworku?</font>
        </p>
        <p>
          <font style="background-color: #00ff00" color="#000000">
          </font>
          <font color="#000000">Ne.
I když Microsoft Compact .Net Framework používá a při nahrání Silverlight aplikace
je patrné z debug logů, že se nahrávají CNF assembly, vlastní CNF aplikaci nenapíšete.
Ale – v poslední části tohoto FAQ o prozatím hypotetické možnosti spouštět CNF aplikace
na WP7 zařízení znovu píšu.</font>
        </p>
        <p>
          <em>
            <font style="background-color: #00ff00" color="#000000">Mohu pro WP7 vyvíjet nativni 
(C/C++) aplikace? Slyšel jsem o nějakém Microsoftem vyvinutém nativním frameworku
Iris.</font>
          </em>
        </p>
        <p>
Stručná odpověď: Nativní aplikace nejsou podporovány, můžete vyvíjet jen Silverlight
aplikace nebo aplikace využívající XNA Framework. Na Iris v klidu zapomeňte.
</p>
        <p>
Složitější odpověď: Nejprve vyřídíme IRIS, což je framework, ke kterém jsem se t<a href="http://twitter.com/#!/renestein/status/28408385225">aké
vyjadřoval na twitteru.</a></p>
        <table border="2" cellspacing="0" cellpadding="2" width="400">
          <tbody>
            <tr>
              <td valign="top" width="396">
Twitter:<br /><em>Objevily se bajky o tajném nativním frameworku IRIS pro </em><a href="http://twitter.com/#!/search?q=%23WP7"><em>#WP7</em></a><em>.
IRIS ale připomíná spíš mix CNF/WPF + P/Invoke. Nativní kód =stále WIN CE API</em></td>
            </tr>
          </tbody>
        </table>
        <p>
          <em>Z</em>de jen dodám, že IRIS si můžete představit jako framework, který v MS vyvinuli
vývojáři, kteří asi nesnášejí technologie WPF/XAML/Silverlight  vytvořené jejich
kolegy, <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /> a
proto si navrhli vlastní značkovací jazyk mixovaný s řízeným kódem a množstvím API
(P/Invoke) volání. IRIS Microsoft pravděpodobně používá v shellu a ve svých WP7 aplikacích.
Jestliže jste se ptali, jak to, že u MS aplikací třeba prvky Pivot a Panorama podporují
plynulejší skrolování než stejné prvky v Silverlightu, v použití IRIS frameworku leží
pravděpodobně odpověď. V Microsoftu buď občas neví levice, ce dělá pravíce, anebo
mobilní Silverlight není zas tak odladěn a vyšperkován, jak by se mohlo z prezentací
demo aplikací u MS evangelistů zdát, a teprve IRIS je tím zázrakem, který rozanimuje
výchozí uživatelské rozhraní a dovede recenzenty WP7 systému k stále opakované větě
o “ďábelské rychlosti WP7 aplikací”. Věta “o ďábelské rychlosti WP7 aplikací” platí
paradoxně do té doby, než začnete další aplikace skutečně instalovat, k čemuž se nadšení
recenzenti už asi nedokopou. Trochu sarkasticky dodejme, že v bajtech zhmotněná IRIS
snad není ve WP7 proto, aby poslala brzy bezduché WP7 do křemíkového pekla, stejně
jako kdysi mytologická Iris pomohla Dídó uvolnit duši z těla.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-winkingsmile_2.png" /></p>
        <p>
          <strong>Nativní kód ale některé aplikace napsané v Silverlightu používají. </strong>Jestliže
si prohlédnete XAP soubory (XAP soubor – distribuční soubor Silverlight aplikace) 
aplikací od výrobcu zařízení, zjistíte, že používají knihovnu GAC_Microsoft.Phone.InteropServices_v7_0_0_0_cneutral_1.dll.
Jak název assembly napovídá, měla by sloužit jako most k nativnímu kódu.
</p>
        <p>
Aplikace od výrobce tuto assembly používají pro dynamické volání metod COM objektů.
Zkusil jsem si napsat jednoduchou COM assembly ve VS 2008 pro Windows CE, protože
VS 2010 z rozhodnutí nějaké moudré hlavy ve vývojářské centrále Microsoftu podporu
pro vývoj CE aplikací již neobsahuje. COM knihovnu jsem nazval SL_COM2.dll.
</p>
        <p>
Poté jsem založil projekt v Silverlightu, přidal do něj soubor nazvaný WPInteropManifest.xml,
který obsahují i aplikace od výrobců. Soubor WPInteropManifest.xml má jednoduchý obsah.
</p>
        <script src="http://gist.github.com/827481.js">
        </script>
        <p>
Do projektu jsem přidal knihovnu GAC_Microsoft.Phone.InteropServices_v7_0_0_0_cneutral_1.dll.
i svou COM knihovnu SL_COM2.dll a u obou knihoven jsem nastavil build akci na content,
aby obě knihovny byly přidány do výsledného XAP souboru. Žádné COM Interop knihovny
nevygenerujete, COM typy musíte naimportovat z COM  knihovny “ručně”.
</p>
        <p>
          <script src="http://gist.github.com/827501.js">
          </script>
        </p>
        <p>
Pomocí reflexe zaregistrujeme COM knihovnu na cílovém zařízení s využitím metod v
assembly GAC_Microsoft.Phone.InteropServices_v7_0_0_0_cneutral_1.dll.
</p>
        <p>
          <script src="http://gist.github.com/827506.js">
          </script>
        </p>
        <p>
Tento kód projde, ale na posledním řádku dostanete výjimku, která znamená, že vaše
COM knihovna je nekompatibilní s aktuální verzí operačního systému. Musíte si na internetu
“najít” a nainstalovat správný Platform builder, <a href="http://blog.walshie.me/2010/11/15/windows-phone-7-full-file-system-access-anyone/#comment-244">což
udělal asi Ch. Welsh, nebo si pohrát s PE hlavičkami knihoven, což jsem udělal já</a>.
COM knihovna by mohla být po odstranění všech překážek i branou ke všem API funkcím,
které si vystavíte v COM objektech. Nepředpokládejte ale, že vaše aplikace bude při
využívání COM knihovny přijata do marketplace.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /></p>
        <p>
          <font style="background-color: #00ff00">Když jsou problémy s umístěním aplikací do
marketplace, je naděje, že brzy bude pro WP7 existovat “jailbreak” a my budeme mít
obchod s neoficiálními aplikacemi? Dají se WP7 “hacknout”?<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /></font>
        </p>
        <p>
Všechno jde, jen to stojí čas a peníze. A musíte mít přitom víru, že WP7 z trhu rychle
nezmizí.
</p>
        <p>
Hlavní problém je podle mě v tom, že Silverlight aplikace běží ve <a href="http://msdn.microsoft.com/en-us/library/dd470128(v=vs.95).aspx">striktním
bezpečnostním modelu</a>, který není snadné překonat. Takže možnosti, které mě napadají:
</p>
        <p>
Metoda pokus-omyl – začneme hledat slabiny v zabezpečení celé CE platformy a doufat,
že Microsoft někde udělal další školáckou chybu podobnou té, kterou využil Chevron,
jen teď někde v mnohem nižších vrstvách systému. Třeba kdyby Microsoft ponechal i
byť jen trochu pootevřen přístup k <a href="http://msdn.microsoft.com/en-us/library/aa920177.aspx">RAPI</a>,
to by byla paráda. Sice se dá “získat” a použít knihovna SmartDevice.Connectivity,
která RAPI interně využívá, ale neodemčený telefon nespolupracuje.
</p>
        <p>
Ukázka volání:
</p>
        <p>
          <script src="http://gist.github.com/827526.js">
          </script>
        </p>
        <p>
Daleko nadějnější mi přijde pokračovat tak, že se do CE registrů přidá vlastní driver,
který po startu zařízení shodí výchozí WP7 shell a dovolí vám nainstalovat a spouštět 
nativní aplikace i aplikace psané v Compact .Net Frameworku. V dalším kroku by to
chtělo nového hostitele Silverlight aplikací, který bude vstřícnější k neoficiálním
aplikacím. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /> Na
některých HTC zařízeních se průnik do registru již podařil… Takže nezbývá než zopakovat:
Všechno jde, jen to stojí čas a peníze.
</p>
        <p>
Snad jste v tomhle článků nalezli alespoň něco zajímavějšího než v konfekčních článcích
o WP7.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png" /></p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=be4f9165-3d77-40c8-aea2-e7f8087f9b70" />
      </body>
      <title>FAQ k WP7 a p&amp;aacute;r specialitek nav&amp;iacute;c &amp;ndash; aneb co jste vždy chtěli vědět o WP7, ale v Microsoftu se v&amp;aacute;m b&amp;aacute;li odpovědět</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,be4f9165-3d77-40c8-aea2-e7f8087f9b70.aspx</guid>
      <link>http://blog.renestein.net/FAQ+K+WP7+A+Paacuter+Specialitek+Naviacutec+Ndash+Aneb+Co+Jste+V%c5%bedy+Cht%c4%9bli+V%c4%9bd%c4%9bt+O+WP7+Ale+V+Microsoftu+Se+Vaacutem+Baacuteli+Odpov%c4%9bd%c4%9bt.aspx</link>
      <pubDate>Tue, 15 Feb 2011 14:23:05 GMT</pubDate>
      <description>&lt;p&gt;
Na twitteru i v emailu se opakuje stále několik dotazů od lidí, kteří koketují s myšlenkou
pořídit si WP7 telefon nebo chtějí pro WP7 vyvíjet. Účelem tohoto článku není suplovat
uživatelský informační servis o WP7, který u nás skvěle dělá &lt;a href="http://www.smartmania.cz"&gt;Smartmania&lt;/a&gt; a
kterému se i&amp;nbsp; v zahraničí&amp;nbsp; věnuje mnoho webů, ale nabídnout snad trochu
jiné informace než ty, které různí nájemní pisálci stále kopírují z tiskových zpráv
a oficiálních prezentací a které další sociálně-altruističtí trotlové bezmyšlenkovitě
linkují, sdílejí a lajkují.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font style="background-color: #00ff00"&gt;Je Windows Phone 7 zcela nový operační
systém, který Microsoft skutečně vyvinul&amp;nbsp; “na zelené louce” a který nemá &lt;strong&gt;NIC&lt;/strong&gt; společného
s Windows Mobile?&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Je i není.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-winkingsmile_2.png"&gt; Neuspokojivá
odpověď ve stylu hárající chytré horákyně, já vím. Windows Phone 7 jsou postaveny
na operačním systému Windows CE, na kterém běžely i Windows Mobile. Dnešní oficiální
název zní &lt;a href="http://msdn.microsoft.com/en-us/library/ee483001.aspx"&gt;Windows
Embedded CE&lt;/a&gt; a aktuální verze má pořadové číslo 6. I Windows Mobile v poslední
verzi 6.5 byly stále založeny na Windows CE 5. Jak vidíte, Microsoft nám to moc neulehčuje
a&amp;nbsp; číslo verze Windows Mobile není nijak závislé na verzi použitých Windows CE.
WP7 dle všech indicií běží na buildu Windows CE 6.
&lt;/p&gt;
&lt;p&gt;
Windows CE 6 mají oprotí Windows CE 5 několik výhod. A z toho plyne, že i WP7 využívají
nových rysů v systému a netrpí hlavními problémy Windows Mobile aplikací.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Ve Windows CE 5 mohlo běžet najednou maximálně 32 procesů. Ano, celých 32 procesů
musí stačit každému, ale s tím, jak se smartphony/PDA/MDA vyvíjely a výrobci ihned
po startu zařízení obsazovali stále více procesních slotů pro své a se zařízením dodávané
aplikace, se tento limit kupodivu ukázal nedostačující. Podpora cca 32 000 procesů
ve Windows CE 6 je pořádné zlepšení. 
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Ve Windows CE 5 měl každý proces 32 MB virtuální paměti a všechny procesy sdílely
4 GB adresní prostor. Nechci zabíhat do detailů, ale způsob nahrávání dynamických
knihoven a jejich sdílení mezi procesy mohl vést velmi rychle k fragmentaci paměti
a k chybě “nedostatek paměti”, i když fyzické paměti bylo dostatek. V CE 6.0 jsou
2 GB virtuálního paměťového prostoru vyhrazeny pro kernel a 2 GB pro každý proces.
Správa paměti v CE 6 má některé nepříjemné dopady na vývojáře kernel/user driverů,
ale pro uživatele i vývojáře aplikací je tento paměťový model mnohem lepší.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Mobilní Silverlight ve WP7 interně využívá Compact .Net Framework, který můžete znát
z Windows Mobile. Jestliže pro WP7 vyvíjíte, poznáte to i podle toho, že při ladění
aplikace a pokusu editovat zdrový kód vám Visual Studio hlásí, že Compact .Net Framework
aplikace nemohou být při ladění upravovány.
&lt;/p&gt;
&lt;p&gt;
Shrnuto – Windows Phone 7 mají nový kabátek (UI Metro), nová běhová prostředí pro
uživatelské aplikace (Silverlight, XNA Framework) a vylepšený podvozek (CE 6). Psát
a hlavně v článcích zdůrazňovat, že WP7 nemají se staršími Windows Mobile &lt;strong&gt;NIC&lt;/strong&gt; společného,
mi přijde v lepším případě naivní, v tom horším okázale neprofesionální. Už minulý
rok jsem psal několikrát , že Microsoft &lt;a href="http://twitter.com/#!/renestein/status/22298585861193730"&gt;by
těžko za pár měsíců vyvinul zcela nový mobilní operační systém&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font style="background-color: #00ff00"&gt;Mohu v ČR nakupovat aplikace v&amp;nbsp; marketplace?&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font style="background-color: #00ff00"&gt;&lt;/font&gt;Stručná odpověď: Ne. 
&lt;/p&gt;
&lt;p&gt;
Složitější odpověď. Microsoft podle neoficiálních informací uvažuje, že marketplace
v ČR bude dostupný “v létě &lt;strike&gt;2010 &lt;/strike&gt;2011”. 
&lt;br&gt;
Neoficiálně to jde – stačí mít zahraniční platební kartu, založit nějaký Live účet,
kde nastavíte, že pocházíte třeba z USA/UK. Ale musíte být asi velcí blázni nebo nadšenci,
abyste si přes tyto obstrukce kupovali dnes (psáno 15.2. 2011) v ČR WP7 telefon. Počítejte
také s tím, že když Microsoft zpřístupní marketplace pro ČR, a vy budete chtít používat
svůj běžný Live účet, zakoupené aplikace mezi různými Live účty nepřevedete.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font style="background-color: #00ff00"&gt;Mohu dnes dát svou WP7 aplikaci do marketplace?&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Stručná odpověď: Ne. 
&lt;br&gt;
Složitější odpověď. Pokud chcete dát aplikaci do marketplace, vyvíjejte se zahraničním
partnerem. Je možné také se s trochou kreativity při tvorbě vývojářského účtu (v komentářích
tohle sousloví vysvětlovat raději nebudu&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt;)
registrovat jako vývojář z jiné země, pokud máte zahraniční platební kartu, ale riskujete,
že Microsoft na tento “trik” přijde a zablokuje vám prodej aplikací, protože porušujete
jeho podmínky.
&lt;/p&gt;
&lt;p&gt;
&lt;font style="background-color: #00ff00"&gt;&lt;em&gt;Dobře, jsem smířen s tím, že se do market
place prozatím nedostanu, ale přesto chci svou aplikaci otestovat na reálném zařízení,
a ne jen v emulátoru. Jak to udělám, když mi WP7 telefon nedovolí nahrát vlastní aplikace?&lt;/em&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font style="background-color: #00ff00"&gt;&lt;/font&gt;Nejjednodušší je dnes použít Chevron
WP7 k neoficiálnímu odemknutí telefonu. Poté co telefon odemknete, můžete nahrávat
své vlastní aplikace. &lt;a href="http://forum.xda-developers.com/showthread.php?t=857127"&gt;Podrobný
návod, jak odemknout telefon, je na XDA-Developers&lt;/a&gt;, takže jej zde nebudu opakovat.
Autoři Chevronu používají na odemčení WP7 telefonu jednoduchý trik. Požadavek na odemčení
telefonu cílený na servery Microsoftu přesměrují na lokální počítač a odemčení telefonu
povolí.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt; Výhodou
je, že nejde o vážný zásah do zařízení, nevýhodou, že pro Microsoft bude snadné tuhle
“díru” (dá se pro tohle amatérské zabezpečení najít nějaký jiný eufemismus?)&amp;nbsp;
uzavřít další plánovanou aktualizací. Microsoft ale po setkání s autory Chevronu přislíbil,
že sám umožní “co nejdříve” vývojářům nahrání a ladění vlastních aplikací v telefonu,
aniž by bylo nutné otevírat a platit za vývojářský účet. Neznámou proměnnou je, které
jednotky pro měření času používá Microsoft, kde, soudě podle stále odkládaného data
první aktualizace pro WP7, korporátní čas evidentně plyne pomaleji, a jestli optimistická
fráze “co nejdříve” zahrnuje alespoň předpokládanou dobu životnosti WP7 na trhu smartphonů.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font style="background-color: #00ff00"&gt;Mohu pro WP7 vyvíjet v Compact .Net Frameworku?&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font style="background-color: #00ff00" color="#000000"&gt;&lt;/font&gt;&lt;font color="#000000"&gt;Ne.
I když Microsoft Compact .Net Framework používá a při nahrání Silverlight aplikace
je patrné z debug logů, že se nahrávají CNF assembly, vlastní CNF aplikaci nenapíšete.
Ale – v poslední části tohoto FAQ o prozatím hypotetické možnosti spouštět CNF aplikace
na WP7 zařízení znovu píšu.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;font style="background-color: #00ff00" color="#000000"&gt;Mohu pro WP7 vyvíjet nativni&amp;nbsp;
(C/C++) aplikace? Slyšel jsem o nějakém Microsoftem vyvinutém nativním frameworku
Iris.&lt;/font&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Stručná odpověď: Nativní aplikace nejsou podporovány, můžete vyvíjet jen Silverlight
aplikace nebo aplikace využívající XNA Framework. Na Iris v klidu zapomeňte.
&lt;/p&gt;
&lt;p&gt;
Složitější odpověď: Nejprve vyřídíme IRIS, což je framework, ke kterém jsem se t&lt;a href="http://twitter.com/#!/renestein/status/28408385225"&gt;aké
vyjadřoval na twitteru.&lt;/a&gt;
&lt;/p&gt;
&lt;table border="2" cellspacing="0" cellpadding="2" width="400"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="396"&gt;
Twitter:&lt;br&gt;
&lt;em&gt;Objevily se bajky o tajném nativním frameworku IRIS pro &lt;/em&gt;&lt;a href="http://twitter.com/#!/search?q=%23WP7"&gt;&lt;em&gt;#WP7&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.
IRIS ale připomíná spíš mix CNF/WPF + P/Invoke. Nativní kód =stále WIN CE API&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
&lt;em&gt;Z&lt;/em&gt;de jen dodám, že IRIS si můžete představit jako framework, který v MS vyvinuli
vývojáři, kteří asi nesnášejí technologie WPF/XAML/Silverlight&amp;nbsp; vytvořené jejich
kolegy, &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt; a
proto si navrhli vlastní značkovací jazyk mixovaný s řízeným kódem a množstvím API
(P/Invoke) volání. IRIS Microsoft pravděpodobně používá v shellu a ve svých WP7 aplikacích.
Jestliže jste se ptali, jak to, že u MS aplikací třeba prvky Pivot a Panorama podporují
plynulejší skrolování než stejné prvky v Silverlightu, v použití IRIS frameworku leží
pravděpodobně odpověď. V Microsoftu buď občas neví levice, ce dělá pravíce, anebo
mobilní Silverlight není zas tak odladěn a vyšperkován, jak by se mohlo z prezentací
demo aplikací u MS evangelistů zdát, a teprve IRIS je tím zázrakem, který rozanimuje
výchozí uživatelské rozhraní a dovede recenzenty WP7 systému k stále opakované větě
o “ďábelské rychlosti WP7 aplikací”. Věta “o ďábelské rychlosti WP7 aplikací” platí
paradoxně do té doby, než začnete další aplikace skutečně instalovat, k čemuž se nadšení
recenzenti už asi nedokopou. Trochu sarkasticky dodejme, že v bajtech zhmotněná IRIS
snad není ve WP7 proto, aby poslala brzy bezduché WP7 do křemíkového pekla, stejně
jako kdysi mytologická Iris pomohla Dídó uvolnit duši z těla.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="Winking smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-winkingsmile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Nativní kód ale některé aplikace napsané v Silverlightu používají. &lt;/strong&gt;Jestliže
si prohlédnete XAP soubory (XAP soubor – distribuční soubor Silverlight aplikace)&amp;nbsp;
aplikací od výrobcu zařízení, zjistíte, že používají knihovnu GAC_Microsoft.Phone.InteropServices_v7_0_0_0_cneutral_1.dll.
Jak název assembly napovídá, měla by sloužit jako most k nativnímu kódu.
&lt;/p&gt;
&lt;p&gt;
Aplikace od výrobce tuto assembly používají pro dynamické volání metod COM objektů.
Zkusil jsem si napsat jednoduchou COM assembly ve VS 2008 pro Windows CE, protože
VS 2010 z rozhodnutí nějaké moudré hlavy ve vývojářské centrále Microsoftu podporu
pro vývoj CE aplikací již neobsahuje. COM knihovnu jsem nazval SL_COM2.dll.
&lt;/p&gt;
&lt;p&gt;
Poté jsem založil projekt v Silverlightu, přidal do něj soubor nazvaný WPInteropManifest.xml,
který obsahují i aplikace od výrobců. Soubor WPInteropManifest.xml má jednoduchý obsah.
&lt;/p&gt;
&lt;script src="http://gist.github.com/827481.js"&gt;&lt;/script&gt;
&lt;p&gt;
Do projektu jsem přidal knihovnu GAC_Microsoft.Phone.InteropServices_v7_0_0_0_cneutral_1.dll.
i svou COM knihovnu SL_COM2.dll a u obou knihoven jsem nastavil build akci na content,
aby obě knihovny byly přidány do výsledného XAP souboru. Žádné COM Interop knihovny
nevygenerujete, COM typy musíte naimportovat z COM&amp;nbsp; knihovny “ručně”.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/827501.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Pomocí reflexe zaregistrujeme COM knihovnu na cílovém zařízení s využitím metod v
assembly GAC_Microsoft.Phone.InteropServices_v7_0_0_0_cneutral_1.dll.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/827506.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Tento kód projde, ale na posledním řádku dostanete výjimku, která znamená, že vaše
COM knihovna je nekompatibilní s aktuální verzí operačního systému. Musíte si na internetu
“najít” a nainstalovat správný Platform builder, &lt;a href="http://blog.walshie.me/2010/11/15/windows-phone-7-full-file-system-access-anyone/#comment-244"&gt;což
udělal asi Ch. Welsh, nebo si pohrát s PE hlavičkami knihoven, což jsem udělal já&lt;/a&gt;.
COM knihovna by mohla být po odstranění všech překážek i branou ke všem API funkcím,
které si vystavíte v COM objektech. Nepředpokládejte ale, že vaše aplikace bude při
využívání COM knihovny přijata do marketplace.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font style="background-color: #00ff00"&gt;Když jsou problémy s umístěním aplikací do
marketplace, je naděje, že brzy bude pro WP7 existovat “jailbreak” a my budeme mít
obchod s neoficiálními aplikacemi? Dají se WP7 “hacknout”?&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Všechno jde, jen to stojí čas a peníze. A musíte mít přitom víru, že WP7 z trhu rychle
nezmizí.
&lt;/p&gt;
&lt;p&gt;
Hlavní problém je podle mě v tom, že Silverlight aplikace běží ve &lt;a href="http://msdn.microsoft.com/en-us/library/dd470128(v=vs.95).aspx"&gt;striktním
bezpečnostním modelu&lt;/a&gt;, který není snadné překonat. Takže možnosti, které mě napadají:
&lt;/p&gt;
&lt;p&gt;
Metoda pokus-omyl – začneme hledat slabiny v zabezpečení celé CE platformy a doufat,
že Microsoft někde udělal další školáckou chybu podobnou té, kterou využil Chevron,
jen teď někde v mnohem nižších vrstvách systému. Třeba kdyby Microsoft ponechal i
byť jen trochu pootevřen přístup k &lt;a href="http://msdn.microsoft.com/en-us/library/aa920177.aspx"&gt;RAPI&lt;/a&gt;,
to by byla paráda. Sice se dá “získat” a použít knihovna SmartDevice.Connectivity,
která RAPI interně využívá, ale neodemčený telefon nespolupracuje.
&lt;/p&gt;
&lt;p&gt;
Ukázka volání:
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/827526.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Daleko nadějnější mi přijde pokračovat tak, že se do CE registrů přidá vlastní driver,
který po startu zařízení shodí výchozí WP7 shell a dovolí vám nainstalovat a spouštět&amp;nbsp;
nativní aplikace i aplikace psané v Compact .Net Frameworku. V dalším kroku by to
chtělo nového hostitele Silverlight aplikací, který bude vstřícnější k neoficiálním
aplikacím. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt; Na
některých HTC zařízeních se průnik do registru již podařil… Takže nezbývá než zopakovat:
Všechno jde, jen to stojí čas a peníze.
&lt;/p&gt;
&lt;p&gt;
Snad jste v tomhle článků nalezli alespoň něco zajímavějšího než v konfekčních článcích
o WP7.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/FAQ-k-WP7_A14B/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=be4f9165-3d77-40c8-aea2-e7f8087f9b70" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,be4f9165-3d77-40c8-aea2-e7f8087f9b70.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Mobilitky</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=1ab0ecc7-7a79-4e17-b2f8-358bd7713695</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=1ab0ecc7-7a79-4e17-b2f8-358bd7713695</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
V <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">předchozích
článcích</a> jsme si vytvořili miniframework pro <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">view
modely</a>   a ukázali si hostitele <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">našich
view modelů</a>. Přišel čas naše znalosti, idiomy a návrhové vzory zakódované ve formě
aplikační infrastruktury v našem miniframeworku využít při tvorbě konkrétní aplikace.
Pro účely tohoto článku i následujících článků jsem se rozhodl, že vytvoříme aplikaci,
která nám dovolí spravovat vlastní blog na doméně <a href="https://posterous.com/">Posterous</a> s
využitím <a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194">Posterous
API</a>.
</p>
        <p>
Hlavní případy užití, které budeme v aplikaci podporovat.
</p>
        <ol>
          <li>
Přihlášení uživatele ke svému účtu  - téma dnešního článku.<br /><br /></li>
          <li>
Zobrazení seznamu blogů, které patří přihlášenému uživateli.<br /><br /></li>
          <li>
Zobrazení seznamu příspěvků na vybraném blogu.<br /><br /></li>
          <li>
Zobrazení detailu příspěvku na blogu.<br /><br /></li>
          <li>
Úprava stávajícího příspěvku na blogu.<br /><br /></li>
          <li>
Zadání nového příspěvku na blog.<br /></li>
        </ol>
        <p>
Jako vždy nás tato prozatím letmo načrtnutá témata dovedou k dalším podivným zákoutím
vývoje WP7 aplikací  a my se z nich s úsměvem záludnostmi WP7 <strike>poučeného
idiota  </strike>zoceleného harcovníka pokusíme dostat.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" />.
</p>
        <p>
Skutečně vás nechci urážet popisem klikání ve Visual Studiu ani popisem základů XAMLu,
“data bindingu”, “behaviors”, takže jen napíšu, že byste před vytvářením aplikace
měli:
</p>
        <ol>
          <li>
Stáhnout si a nainstalovat <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&amp;displaylang=en">Windows
Phone Developer Tools.</a><br /><br /></li>
          <li>
Ve Visual Studiu založte nový projekt Windows Phone Application – nejlepší bude, když
ho pojmenujete jako já <em>RStein.PosterousReader.WP</em>, abyste nebyli zmateni názvy
jmenných prostorů dále v článku.<br /><br /><a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_5.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_1.png" width="244" height="170" /></a><br />
  
</li>
          <li>
Vývojářský život je na tomto projektu jednodušší o to, že k práci s Posterous API
použijeme můj <a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194">C#
Posterous API Wrapper pro WP7</a>.  Po stažení přidejte referenci na knihovnu <em>RStein.Posterous.API.SLM </em>do
svého projektu.<br />
A i když to dnes ještě není tak nutné, <a href="https://posterous.com/">zřiďte si
na Posterous vlastní účet</a>, abyste mohli aplikaci později testovat na reálných
datech. C# Posterous API pro nás v triádě Model-View-ViewModel bude představovat model,
což má pro nás výhodu, že se můžeme stále soustředit na view a view modely, o které
šlo i v předchozích článcích, a model můžeme považovat za černou skříňku.<br /><br /></li>
          <li>
V novém projektu vytvořte hlavně dvě nové složky View a ViewModels. Na obrázku jsou
červeně podtrženy další složky, které si již dnes doporučuju přidat do projektu 
- Behaviors, Extensions, HostServices, Icons, SpecialTypes, UI, UIServices a hlavně
ViewModels a Views.<br /><br /><br /><a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_7.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_2.png" width="94" height="244" /></a><br /><br /></li>
          <li>
Předpokládám, že jste schopni do svého projektu vložit kód tříd, které jsem popisoval
v předchozích článcích. Seznam předchozích článků s výpisy kódu naleznete na konci
tohoto článku.</li>
        </ol>
        <p>
Dnes vytvoříme přihlašovací obrazovku do naší aplikace. Pro lepší představu je zde
obrazovka, kterou byste měli mít hotovou na konci dnešního článku.
</p>
        <p>
          <img src="http://blog.renestein.net/content/binary/Windows-Live-Writer/C-Posterous-API-.3--s-podporou-i-pro-WP7_D37E/image_2.png" width="379" height="633" />
        </p>
        <p>
  
</p>
        <p>
Nejprve určíme, které funkce musí obrazovka a její podkladový kód zvládat: 
</p>
        <ol>
          <li>
Přihlašovací obrazovka se zobrazí ihned po startu aplikace.<br /><br /></li>
          <li>
Uživateli dovolíme zadat přihlašovací jméno a heslo.<br /><br /></li>
          <li>
Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno heslo,
tlačítko Přihlásit se je neaktivní.<br /><br /></li>
          <li>
Jestliže dojde k <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">“tombstoningu</a>”
stránky, bude jméno i heslo po návratu z “tombstonovaného” stavu zachováno – ověříme
si tak poprvé in vivo, že <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">naše
třída ViewModelBase podporuje “tombstoning” přesně dle našich požadavků</a>.<br /><br /></li>
          <li>
Po návratu na přihlašovací obrazovku z jiné části aplikace bude zachován jen obsah
textového pole “uživatelské jméno”, textové pole “heslo” bude prázdné.<br /><br /></li>
          <li>
Po kliknutí na tlačítko Přihlásit nebudeme zadané jméno a heslo ihned ověřovat, ale
uložíme oba údaje  pro použití na dalších stránkách aplikace. Poté přesměrujeme
uživatele na další stránku se seznamem blogů, kde bude jméno a heslo využito k získání
seznamu blogů uživatele. Důvodem je to, že v Posterous API se jméno a heslo zasílá
při každém webovém požadavku, žádné jednorázové přihlášení neexistuje a nemá smysl
generovat nějaký “dummy” požadavek jen pro ověření hesla. Jestliže se na stránce se
seznamem blogů, na kterou z přihlašovací obrazovky přesměrováváme, data kvůli neplatným
přihlašovacím údajům získat nepodaří, aplikace nás vrátí na přihlašovací obrazovku.
Vytvoření stránky se seznamem blogů bude téma dalšího článku.<br /></li>
        </ol>
        <p>
A začínáme: 
</p>
        <p>
Do složky Views vložte nové View pro přihlášení uživatele. V dialogu Add new item
vyberte Windows Phone Portrait Page a pojmenujte ji MainLoginView.xaml.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_9.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_3.png" width="244" height="170" />
          </a>
        </p>
        <p>
Jedná se o úvodní  stránku aplikace, a proto v deskriptoru WP7 aplikace nazvaném
WAMppManifest.xml, který naleznete v projektové složce Properties, změníme startovací
stránku na View/mainLoginView.xaml. <script src="https://gist.github.com/793066.js"></script></p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_13.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_5.png" width="244" height="154" />
          </a>
        </p>
        <p>
I když to není u přihlašovacího dialogu nutné, v dnešním článku si ukážeme, jak můžeme
jednoduše složit jedno view z dalších nezávislých view a také to, že view nemusí být
jen stránka (Page), ale i “User Control”. Naše MainLoginView bude zobrazovat titulek
aplikace (Posterous klient), titulek stránky (Přihlášení) , ale textová pole “heslo”,
“uživatelské jméno” a tlačítko “Přihlásit" se” bude obsahovat “user control” LoginView,
který můžeme použít jako součást i zcela jiného view (stránky) v aplikaci.  Do
složky Views přidejte Windows Phone User Control a nazvěte jej LoginView.xaml. 
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_15.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_6.png" width="244" height="170" />
          </a>
        </p>
        <p>
Zkompilujte (Build) “solution”. 
</p>
        <p>
Do view MainLoginView vložte tento kód: 
</p>
        <p>
          <script src="http://gist.github.com/793080.js">
          </script>
        </p>
        <p>
Jak jsem zmiňoval v <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">jednom
z předešlých článků</a>, všechny stránky v aplikaci by měly být potomkem naší třídy <a href="https://gist.github.com/763320">PageBase</a>,
která je hostitelem pro view modely. Proto je naše stránka uzavřena v elementu <em>&lt;controlex:PageBase&gt;</em>. 
XML jmenný prostor controleex je u mě namapován na xmlns:controlex="clr-namespace:RStein.PosterousReader.WP.UI".
V projektovém adresáři UI musíte mít tedy třídu PageBase.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_19.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_8.png" width="244" height="154" />
          </a>
        </p>
        <p>
Také v “code behind souboru” musíte třídu MainLoginView učinit potomkem PageBase.
</p>
        <script src="https://gist.github.com/793085.js">
        </script>
        <p>
Hlavní xaml pro přihlášení uživatele obsahuje “User Control” LoginView, na který se
v MainLoginView odkazujeme. <em>(&lt;views:LoginView Grid.Row="1"&gt;&lt;/views:LoginView&gt;</em>). 
XML jmenný prostor <em>views</em> je mapován na jmenný prostor <em>RStein.PosterousReader.WP.Views </em>v
C# (<em>xmlns:views="clr-namespace:RStein.PosterousReader.WP.Views</em>) – v našem
případě tedy na projektový adresář Views.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_17.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_7.png" width="244" height="154" />
          </a>
        </p>
        <p>
Do view s názvem LoginView vložte následující XAML:
</p>
        <script src="https://gist.github.com/793102.js">
        </script>
        <p>
Jak bylo vidět na snímku obrazovky na počátku článku, LoginView obsahuje hlavně textové
pole pro zadání jména uživatele (txtName) a prvek pro zadání hesla uživatele (txtPassword)
a tlačítko “Přihlásit se”. U prvků pro zadání uživatelského jména a hesla vás mohou
zarazit jen tagy &lt;i:Interaction.Behaviors&gt; a atributy <em>jako behaviors:TextboxPasswordAttachedProperties.TextBoxChangedAction</em>,
jejichž význam vysvětlím za chvíli. Také vás hned  upozorním, že tlačítko “Přihlásit
se” je speciální tlačítko ((<em>&lt;controlex:ButtonEx</em>) dovolující reagovat na
stisknutí tlačítka uživatelem tak, že spustí metodu Execute objektu ICommand, což
standardní WP7 tlačítko nezvládá. Znovu  připomínám, že Silverlight ve WP7 je
bohužel založen na poměrně staré verzi 3 desktopového Silverlightu. Kód třídy ButtonEx
uvidíte také za chvíli.
</p>
        <p>
Máme view, ve view používáme “data binding”, ale nemáme ještě view modely, které fungují
pro view jako zdroj dat. 
</p>
        <p>
          <strong>V každém view modelu naší aplikace </strong>budeme používat objekt <em>IPosterousApplication</em> ke
komunikaci s Posterous, budeme chtít z view modelů navigovat na další view v aplikaci
a také bychom měli být schopni v každém view modelu získat  uživatelské jméno
a heslo zadané na na námi vytvářené přihlašovací obrazovce. To znamená, že společné
vlastnosti a služby view modelů pro naši aplikaci můžeme soustředit v bázové třídě
PosterousViewModelBase. Do projektové složky Views vložte novou třídu PosterousViewModelBase
a do ní zkopírujte následující kód. 
</p>
        <p>
PosterousViewModelBase je potomkem <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">naší
staré známé třídy ViewModelBase</a></p>
        <p>
          <script src="http://gist.github.com/793123.js">
          </script>
        </p>
        <p>
V konstruktoru třída PosterousViewModelBase přijímá odkaz na objekt <em>IPosterousApplication</em>,
který je základním rozcestnikem pro přístup k Posterous API, navigační službu <em>INavigationService</em>,
která view modelu dovolí navigovat na další view v aplikaci  (např. ze seznamu
článků na detail vybraného článku), a titulek zobrazené stránky.  <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Titulek
převezme a nabízí poté ve vlastnosti PageTitle bázová třída ViewModelBase.</a></p>
        <p>
Navigační služba je představována rozhraním <em>INavigationService.</em></p>
        <p>
          <script src="http://gist.github.com/793126.js">
          </script>
        </p>
        <p>
Základní implementace rozhraní <em>INavigationService</em> pro WP7 je dostupná ve
třídě <em>DefaultWPNavigationService</em> a pouze obaluje navigační služby dostupné
v samotných WP7 aplikacích. 
</p>
        <script src="http://gist.github.com/793133.js">
        </script>
        <p>
Rozhraní <em>INavigationService</em> i třídu <em>DefaultWPNavigationService</em> vložte
do projektové složky HostServices.Více si o navigaci mezi různými view povíme v dalších
článcích.
</p>
        <p>
Vraťmě se k PosterousViewModelBase. V PosterousViewModelBase máme vždy uloženo ve
statických vlastnostech LastUsedUserName a LastUsedPassword poslední zadané přihlašovací
údaje, které může každý view model využít při získání nebo úpravě dat z Posterous. 
</p>
        <p>
          <em>Poznámka: Kdyby někoho z vás pohoršovali statické vlastnosti, klidně si jako domácí
úkol napište “CredentialsManager”, který bude injektován stejně jako již zmíněné dvě
další služby do view modelů. Prozatím nechci komplikovat kód víc, než je nutné.</em>
        </p>
        <p>
My máme dvě view, MainLoginView a LoginView, a proto vytvoříme i dva view modely.
Opět zdůrazňuju, že tato volba je na vás <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">a
díky “dědění view modelů”</a> bychom mohli ponechat třeba dvě view a vytvořit pro
ně jen jeden společný view model. 
</p>
        <p>
Do projektové složky ViewModels přidejte třídu nazvanou MainLoginViewModel – view
model pro MainLoginView. <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">Název
view modelu nyní musí odpovídat konvenci “NázevView +ViewModel”. Zdůrazňuju i zde,
že jde jen o konvenci a že si můžete jednoduše napsat jiný IViewModelResolver, který
dohledá dle vašich zcela jiných projektových konvencí k view vhodný view model.</a></p>
        <p>
MainLoginViewModel je sympaticky jednoduchý objekt. Má jen delegující konstruktor,
ve kterém předá své bázové třídě PosterousViewModelBase vyžadované povinné argumenty
posterousApplication, navigationService a titulek stránky. 
</p>
        <p>
          <script src="http://gist.github.com/793149.js">
          </script>
        </p>
        <p>
Texty v aplikaci nejsou prozatím lokalizovány a titulky stránek jsou uloženy ve třídě
GlobalConstants. Do “rootu” projektu přidejte třídu GlobalConstants.cs 
</p>
        <p>
          <script src="http://gist.github.com/793153.js">
          </script>
        </p>
        <p>
Název aplikace (APP_MAIN_TITLE) , podobně jako titulek stránky, <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">vydává
ve vlastnosti AppTitle  opět ViewModelBase</a></p>
        <p>
Jen o trochu složitější bude view model pro LoginView. Do projektové složky ViewModels
přidejte třídu LoginViewModel. 
</p>
        <p>
          <script src="http://gist.github.com/793171.js">
          </script>
        </p>
        <p>
V LoginViewModelu máme opět delegující konstruktor, jedinou změnou oproti MainLoginViewModelu
je to, že jako titulek stránky předáváme prázdný řetězec, protože předpokládáme, že
titulek na stránku dodá “nadřízené” view.
</p>
        <p>
Vlastnosti a jejich význam
</p>
        <table border="1" cellspacing="0" cellpadding="2" width="656">
          <tbody>
            <tr>
              <td valign="top" width="166">
                <strong>Název vlastnosti</strong>
              </td>
              <td valign="top" width="488">
                <strong>Popis</strong>
              </td>
            </tr>
            <tr>
              <td valign="top" width="170">
TextChangedAction</td>
              <td valign="top" width="484">
Akce, která má být vyvolána, když se ve view změní text přihlašovacího jména nebo
hesla. Tato akce je v konstruktoru inicializována tak, že si vynutíme opětovné vyhodnocení
toho, zda může být proveden LoginCommand. V článku popíšu, proč je to (prozatím?)
řešeno takto.</td>
            </tr>
            <tr>
              <td valign="top" width="170">
LoginCommand</td>
              <td valign="top" width="484">
Objekt podporující rozhraní ICommand,  který v metodě Execute zavolá metodu handleLogin.
Metoda handleLogin uloží zadané jméno a heslo do statických vlastností LastUsedPassword
a a LastUsedUserName a přesměruje uživatele na stránku se seznamem blogů. Instanční
vlastnost UserPassword je při každém pokusu o navigaci na stránku se seznamem blogů
“vyčištěna” tím, že je do ní uložen prázdný řetězec, a při návratu na přihlašovací
obrazovku tedy není automaticky předvyplněno heslo, což byl jeden z našich požadavků
na přihlašovací dialog.<br />
LoginCommand může být proveden jen tehdy, když bylo ve view zadáno a do view modelu
přes oboustranný (two way) binding zpropagováno uživatelské jméno a heslo. Pokud vlastnosti
UserName a UserPassword mají hodnotu null nebo obsahují prázdný řetězec, LoginCommand
nemůže být proveden.</td>
            </tr>
            <tr>
              <td valign="top" width="170">
UserName</td>
              <td valign="top" width="484">
Zadané přihlašovací jméno na službu Posterous. V <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">metodě
DoInternalInit, která je volána na začátku životního cyklu view modelu</a> předvyplníme
uživatelské jméno posledním zadaným uživatelským jménem, které jsme dříve uložili
do statické vlastnosti LastUsedUserName.</td>
            </tr>
            <tr>
              <td valign="top" width="170">
UserPassword</td>
              <td valign="top" width="484">
Heslo na službu Posterous.</td>
            </tr>
          </tbody>
        </table>
        <p>
Co potřebujeme, abychom mohli náš LoginViewModel zkompilovat? 
</p>
        <p>
Do třídy GlobalConstants přidejte URL dalšího view se seznamem blogů a článků. 
</p>
        <p>
          <script src="http://gist.github.com/793195.js">
          </script>
        </p>
        <p>
Stránku PostsListView.xaml vytvoříme v dalším článku, nyní ji celou vytvářet nemusíte.
Postačí do složky Views dát novou stránku (Page) s názvem PostsListView.xaml. 
</p>
        <p>
Jak jsem již psal, ve WP7 nemáme bohužel podporu pro objekty ICommand. Třída DelegateCommand,
jejíž instancí je LoginCommand, <strong>je minimalistickou implementací </strong>rozhraní
ICommand. 
</p>
        <p>
Pokud podobnou třídu nemáte, vložte si  do projektu třídu DelegateCommand. U
mě je v jmenném prostoru <strong>RStein.PosterousReader.Common.</strong></p>
        <p>
          <strong>
            <script src="http://gist.github.com/793206.js">
            </script>
          </strong>
        </p>
        <p>
Třídě DelegateCommand můžete předat dva delegáty. Delegát executeAction (“co má být
vykonáno”) je spuštěn v metodě Execute z rozhraní ICommand. Delegát canExecuteAction
představuje implementaci metody CanExecute (“může být  nyní command vykonán?”).
Minimalistická implementace je to proto, že nijak nepoužívám událost CanExecuteChanged,
a namísto toho jsem si pro “binding” vystavil speciální vlastnost CanExecuteCommand,
která v get akcesoru deleguje na metodu CanExecute.
</p>
        <p>
Vlastnost TextChangedAction v LoginViewModelu je delegát typu Action, který nám pomáhá
vyřešit jeden z požadavků na přihlášení. 
</p>
        <p>
          <em>“Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno
heslo, tlačítko Přihlásit se je neaktivní.”</em>
        </p>
        <p>
To znamená, že potřebujeme po každém přidání nebo smazání znaku v textboxu pro zadání
jména uživatele i v textboxu pro zadání hesla zjišťovat, jestli můžeme ve view zpřístupnit
tlačítko pro přihlášení. Když je alespoň jeden textbox prázdný, tlačítko pro přihlášení
není dostupné, když je vyplněno alespoň jedním znakem jméno i heslo, tlačítko pro
přihlášení je dostupné.
</p>
        <p>
Jak je tento požadavek ve view a view modelu splněn?
</p>
        <p>
Ve view <em>LoginView</em> je vlastnost <em>IsEnabled</em> tlačítka “Přihlásit se“
z třídy <em>ButtonEx</em> “nabindována” na vlastnost <em>CanExecuteCommand</em> objektu <em>LoginCommand</em> ve
view modelu.
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_21.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_9.png" width="244" height="154" />
          </a>
        </p>
        <p>
Do projektové složky UI si přidejte třídu ButtonEx, která doplňuje standardní WP7
tlačítko o jednoduchou podporu objektů ICommand.
</p>
        <p>
          <strong>
            <script src="http://gist.github.com/793221.js">
            </script>
          </strong>
        </p>
        <p>
Vlastnost CanExecuteCommand musí vracet true, pokud je v každém textboxu alespoň jeden
znak, jinak false. Jak ale ve view modelu zjistíme, že uživatel zadal nebo smazal
v některém textovém poli další znak? Do view modelu se při oboustranném bindingu zpropaguje
hodnota z textového pole až po opuštění textového pole uživatelem, ale my přitom musíme
reagovat ve view modelu na zadání každého znaku.
</p>
        <p>
Takové chování textových polí ve WP7 skutečně nemáme a musíme si ho dopsat, a to nejlépe
za pomoci ”attached” vlastností a objektů <em>Behavior&lt;T&gt;</em>. Nejprve se podívejme,
jak vypadají objekty TextBox a PasswordBox v XAMLu, když jsou rozšířeny o “attached”
vlastnost <em>TextboxPasswordAttachedProperties.TextBoxChangedAction</em>, která je
“nabindována” na nám již známou vlastnost TextChangedAction typu Action ve view modelu. 
“Attached” vlastnost <em>TextBoxChangedAction</em> tedy říká: “Hej, kdykoli se změní
u prvku zadaný text, musí NĚKDO ochotný zavolat delegáta TextChangedAction, abychom
ve view modelu nebyli odříznuti od novinek ve světě view.”
</p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_23.png">
            <img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_10.png" width="244" height="154" />
          </a>
        </p>
        <p>
A ten někdo bude náš objekt Behavior , který zase světu sděluje: “Mám dobré vychování,
a když mi dovolíte vstoupit do bran tagu PasswordBox nebo TextBox, delegáta TextChangedAction
zavolám,  i když to sám WP7 TextBox a PasswordBox nezvládne.”
</p>
        <p>
          <script src="http://gist.github.com/793240.js">
          </script>
        </p>
        <p>
Další nepříjemností ve WP7 je, že i když objekt Behavior má mít pro TextBox a PasswordBox 
stejné chování, musíme napsat dva objekty Behavior pro každý prvek, protože TextBox
ani PasswordBox spolu kupodivu nemají moc společného. My se alespoň pokusíme kód v
obou objektech Behavior neduplikovat.
</p>
        <p>
 
</p>
        <p>
Do projektové složky Behaviors přidejte třídu TextboxPasswordAttachedProperties a
v ní vytvořte attached vlastnost TextBoxChangedAction.
</p>
        <p>
          <script src="http://gist.github.com/793248.js">
          </script>
        </p>
        <p>
Do složky Behaviors přidejte abstraktní třídu TextChangedBehaviorBase, která bude
fungovat jako základ pro dva podobné objekty Behavior určené pro TextBox (TextBoxTextChangedUpdateSourceBehavior)
a PasswordBox (PasswordTextChangedBehavior). <strong>Do projektu musíte přidat referenci
na knihovnu System.Windows.Interactivity, </strong>kterou naleznete většinou ve složce <em>c:\Program
Files\Microsoft SDKs\Expression\Blend\Windows Phone\v7.0\Libraries\System.Windows.Interactivity.dll. </em><strong>Bez
této knihovny není dostupná bázová třída Behavior&lt;T&gt;.</strong></p>
        <p>
          <script src="http://gist.github.com/793259.js">
          </script>
        </p>
        <p>
Metoda RunTextChangedAction se pro objekt Textbox a PasswordBox asociovaný s tímto
objektem Behavior  pokusí dohledat a spustit delegáta v “attached” vlastnost
TextBoxChangedAction. Metoda UpdateSource požádá odvozené třídy o vydání "objektu
BindingExpression” voláním metody GetBindingExpression. Vrácený objekt “BindingExpression“
by měl  zapouzdřovat propojení vlastnosti view modelu (např UserName) s textem
v textovém poli. Po kontrole, že se jedná o oboustranný (two way) binding, metoda
UpdateSource zavolá na objektu BindingExpression UpdateSource, což způsobí přenesení
hodnoty zadané uživatelem v textovém poli ve view do zdrojové vlastnosti (např. UserName)
ve view modelu.
</p>
        <p>
Potomek TextBoxTextChangedUpdateSourceBehavior v metodě GetBindingExpression vrátí
BindingExpression pro svou vlastnost Text. V přepsané metodě OnAttached, která je
volána vždy, když je objekt Behavior asociován s textboxem, si přihlásíme odběr události
TextChanged TextBoxu a při každé změně textu voláme zděděné a výše popsané metody
UpdateSource a RunTextChangedAction. V metodě OnDetaching si nezapomeneme odběr události
TextChanged odhlásit.
</p>
        <script src="http://gist.github.com/793285.js">
        </script>
        <p>
Pro PasswordBox máme dalšího potomka PasswordTextChangedBehavior, který se od třídy
TextBoxTextChangedUpdateSourceBehavior liší jen tím, že v metodě GetBindingExpression
vrací “BindingExpression” pro vlastnost Password a zadávaný text sleduje přes událost
PasswordChanged.
</p>
        <script src="https://gist.github.com/793557.js">
        </script>
        <p>
 
</p>
        <p>
V LoginView si nezapomeňte zkontrolovat, že máte namapovány správně xml prefixy <em>behaviors</em> a <em>i</em><strong></strong>na
správné jmenné prostory v C#, abyste mohli využívat novou attached vlastnost TextBoxChangedAction
a objekty TextBoxTextChangedUpdateSourceBehavior  a PasswordTextChangedBehavior.
</p>
        <p>
          <em>prostoryxmlns:behaviors="clr-namespace:RStein.PosterousReader.WP.Behaviors"<br />
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"</em>
        </p>
        <p>
          <a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_25.png">
            <img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_11.png" width="244" height="154" />
          </a>
        </p>
        <p>
Dodejme, že náš delegát TextChangedAction ve view modelu simuluje změnu objektu LoginCommand,
který je přidružen k tlačítku Přihlásit se a tlačítko Přihlásit tedy po každém zadání
znaku zjistí, jestli má být dostupné.  Zopakujme, že vlastnost IsEnabled tlačítka
je “nabindována” na vlastnost LoginCommand.CanExecuteCommand. 
</p>
        <p>
Aplikaci můžete spustit.
</p>
        <p>
          <em>Poznámka: Ještě si ale nezapomeňte do složky UIServices dát kód rozhraní IViewModelResolver
a třídy ViewModelResolver, které jsem popisoval v článku </em>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">
            <em>propojení
view modelu s view (stránkou)</em>
          </a>
          <em>, protože bez třídy ViewModelResolver by
aplikace nebyla schopna pro naše MainLoginView a LoginView dohledat právě vytvořené
view modely. A v aplikaci musíte mít samozřejmě všechny další třídy z předchozích
článků, které jsou odpovědné za “tombstoning” apod.</em>
        </p>
        <p>
U aplikace si můžete zkontrolovat, že:
</p>
        <ul>
          <li>
Přihlašovací dialog plní všechny požadavky, které jsme vypsal  na začátku článku.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" /><br /><br /></li>
          <li>
Nemusíme se nijak starat o “tombstoning” aplikace. Zmáčkněte tlačítko Win, poté se
tlačítkem Back vraťte do aplikace a všechny hodnoty v textových polích zůstanou zachovány.<br /><br /></li>
          <li>
Tlačítko pro přihlášení je dostupné jen tehdy, když textová pole pro zadání jména
a hesla jsou vyplněna. Pokud alespoň jedno pole vyplněno není, tlačítko je neaktivní.<br /><br /></li>
          <li>
I naše minimalistická podpora rozhraní ICommand vede k tomu, že ve View nemáme žádný 
“code behind”. Logika stojící za view je jen ve view modelech a XAML tahá data z view
modelů přes “data binding”. Pokud přesně tohle to považujete za důležité, budete určitě
nadšeni. Jak uvidíte v dalších článcích, já jsem vůči strategii “vše do XAMLu” hodně
skeptický, ale XAML puristé <strike>si </strike>mohou jít po dnešku jistě <strike>ožrat
držku </strike>slavit<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" />.<br /><br /></li>
          <li>
I když šlo jen o přihlašovací formulář, vytvořili jsme si další skládací kostky (attached
vlastnosti, Behavior, PosterousViewModelBase), které se nám budou hodit při psani
dalších view a view modelů (nejen)  v této aplikaci.<br /></li>
        </ul>
        <p>
Zauvažujte nad tím, jestli by se nám také nehodila nějaká podpora ve view modelech
pro ukládání nejen tranzientního stavu, ale i pro ukládání “trvalejšího” stavu, který
bude dostupný i v další nezávislé instanci aplikace. Možná by stálo za to, aby si
aplikace pamatovala poslední zadané přihlašovací jméno nejen při “tombstoningu”, ale
aby přihlašovací jméno bylo nabídnuto i při novém spuštění aplikace. A z hlediska
vývojáře  bezbolestná podpora pro ukládání perzistentního stavu (<a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">data
s “delší záruční lhůtou”</a>) bude námětem dalšího WP7 intermezza. Doufám, že se těšíte. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png" /></p>
        <p>
          <strong>Předchozí články:<br /><br /></strong>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx">Tipy
pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IV+Intermezzo+I+Zjednoduscaronenaacute+Registrace+Serializovatelnyacutech+T%c5%99iacuted+Nesouciacutech+Tranzientniacute+Stav+V+KnownTypesDictionary.aspx">Tipy
pro Windows Phone 7 aplikace IV - intermezzo I - zjednodušená registrace serializovatelných
tříd nesoucích tranzientní stav v KnownTypesDictionary</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=1ab0ecc7-7a79-4e17-b2f8-358bd7713695" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace V &amp;ndash; vytv&amp;aacute;ř&amp;iacute;me prvni aplikaci (a stav&amp;iacute;me ji na vytvořen&amp;yacute;ch z&amp;aacute;kladech)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+V+Ndash+Vytvaacute%c5%99iacuteme+Prvni+Aplikaci+A+Staviacuteme+Ji+Na+Vytvo%c5%99enyacutech+Zaacutekladech.aspx</link>
      <pubDate>Mon, 24 Jan 2011 16:48:26 GMT</pubDate>
      <description>&lt;p&gt;
V &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;předchozích
článcích&lt;/a&gt; jsme si vytvořili miniframework pro &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;view
modely&lt;/a&gt;&amp;nbsp;&amp;nbsp; a ukázali si hostitele &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;našich
view modelů&lt;/a&gt;. Přišel čas naše znalosti, idiomy a návrhové vzory zakódované ve formě
aplikační infrastruktury v našem miniframeworku využít při tvorbě konkrétní aplikace.
Pro účely tohoto článku i následujících článků jsem se rozhodl, že vytvoříme aplikaci,
která nám dovolí spravovat vlastní blog na doméně &lt;a href="https://posterous.com/"&gt;Posterous&lt;/a&gt; s
využitím &lt;a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194"&gt;Posterous
API&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Hlavní případy užití, které budeme v aplikaci podporovat.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Přihlášení uživatele ke svému účtu&amp;nbsp; - téma dnešního článku.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zobrazení seznamu blogů, které patří přihlášenému uživateli.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zobrazení seznamu příspěvků na vybraném blogu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zobrazení detailu příspěvku na blogu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Úprava stávajícího příspěvku na blogu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Zadání nového příspěvku na blog.&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Jako vždy nás tato prozatím letmo načrtnutá témata dovedou k dalším podivným zákoutím
vývoje WP7 aplikací&amp;nbsp; a my se z nich s úsměvem záludnostmi WP7 &lt;strike&gt;poučeného
idiota&amp;nbsp; &lt;/strike&gt;zoceleného harcovníka pokusíme dostat.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;.
&lt;/p&gt;
&lt;p&gt;
Skutečně vás nechci urážet popisem klikání ve Visual Studiu ani popisem základů XAMLu,
“data bindingu”, “behaviors”, takže jen napíšu, že byste před vytvářením aplikace
měli:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Stáhnout si a nainstalovat &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=04704acf-a63a-4f97-952c-8b51b34b00ce&amp;amp;displaylang=en"&gt;Windows
Phone Developer Tools.&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Ve Visual Studiu založte nový projekt Windows Phone Application – nejlepší bude, když
ho pojmenujete jako já &lt;em&gt;RStein.PosterousReader.WP&lt;/em&gt;, abyste nebyli zmateni názvy
jmenných prostorů dále v článku.&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_5.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_1.png" width="244" height="170"&gt;&lt;/a&gt;
&lt;br&gt;
&amp;nbsp; 
&lt;li&gt;
Vývojářský život je na tomto projektu jednodušší o to, že k práci s Posterous API
použijeme můj &lt;a href="http://posterousapi.codeplex.com/releases/view/55736#DownloadId=167194"&gt;C#
Posterous API Wrapper pro WP7&lt;/a&gt;.&amp;nbsp; Po stažení přidejte referenci na knihovnu &lt;em&gt;RStein.Posterous.API.SLM &lt;/em&gt;do
svého projektu.&lt;br&gt;
A i když to dnes ještě není tak nutné, &lt;a href="https://posterous.com/"&gt;zřiďte si
na Posterous vlastní účet&lt;/a&gt;, abyste mohli aplikaci později testovat na reálných
datech. C# Posterous API pro nás v triádě Model-View-ViewModel bude představovat model,
což má pro nás výhodu, že se můžeme stále soustředit na view a view modely, o které
šlo i v předchozích článcích, a model můžeme považovat za černou skříňku.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
V novém projektu vytvořte hlavně dvě nové složky View a ViewModels. Na obrázku jsou
červeně podtrženy další složky, které si již dnes doporučuju přidat do projektu&amp;nbsp;
- Behaviors, Extensions, HostServices, Icons, SpecialTypes, UI, UIServices a hlavně
ViewModels a Views.&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_7.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_2.png" width="94" height="244"&gt;&lt;/a&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Předpokládám, že jste schopni do svého projektu vložit kód tříd, které jsem popisoval
v předchozích článcích. Seznam předchozích článků s výpisy kódu naleznete na konci
tohoto článku.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Dnes vytvoříme přihlašovací obrazovku do naší aplikace. Pro lepší představu je zde
obrazovka, kterou byste měli mít hotovou na konci dnešního článku.
&lt;/p&gt;
&lt;p&gt;
&lt;img src="http://blog.renestein.net/content/binary/Windows-Live-Writer/C-Posterous-API-.3--s-podporou-i-pro-WP7_D37E/image_2.png" width="379" height="633"&gt;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp; 
&lt;p&gt;
Nejprve určíme, které funkce musí obrazovka a její podkladový kód zvládat: 
&lt;ol&gt;
&lt;li&gt;
Přihlašovací obrazovka se zobrazí ihned po startu aplikace.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Uživateli dovolíme zadat přihlašovací jméno a heslo.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno heslo,
tlačítko Přihlásit se je neaktivní.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jestliže dojde k &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;“tombstoningu&lt;/a&gt;”
stránky, bude jméno i heslo po návratu z “tombstonovaného” stavu zachováno – ověříme
si tak poprvé in vivo, že &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;naše
třída ViewModelBase podporuje “tombstoning” přesně dle našich požadavků&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Po návratu na přihlašovací obrazovku z jiné části aplikace bude zachován jen obsah
textového pole “uživatelské jméno”, textové pole “heslo” bude prázdné.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Po kliknutí na tlačítko Přihlásit nebudeme zadané jméno a heslo ihned ověřovat, ale
uložíme oba údaje&amp;nbsp; pro použití na dalších stránkách aplikace. Poté přesměrujeme
uživatele na další stránku se seznamem blogů, kde bude jméno a heslo využito k získání
seznamu blogů uživatele. Důvodem je to, že v Posterous API se jméno a heslo zasílá
při každém webovém požadavku, žádné jednorázové přihlášení neexistuje a nemá smysl
generovat nějaký “dummy” požadavek jen pro ověření hesla. Jestliže se na stránce se
seznamem blogů, na kterou z přihlašovací obrazovky přesměrováváme, data kvůli neplatným
přihlašovacím údajům získat nepodaří, aplikace nás vrátí na přihlašovací obrazovku.
Vytvoření stránky se seznamem blogů bude téma dalšího článku.&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
A začínáme: 
&lt;p&gt;
Do složky Views vložte nové View pro přihlášení uživatele. V dialogu Add new item
vyberte Windows Phone Portrait Page a pojmenujte ji MainLoginView.xaml.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_9.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_3.png" width="244" height="170"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Jedná se o úvodní&amp;nbsp; stránku aplikace, a proto v deskriptoru WP7 aplikace nazvaném
WAMppManifest.xml, který naleznete v projektové složce Properties, změníme startovací
stránku na View/mainLoginView.xaml. &lt;script src="https://gist.github.com/793066.js"&gt; &lt;/script&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_13.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_5.png" width="244" height="154"&gt;&lt;/a&gt; 
&lt;p&gt;
I když to není u přihlašovacího dialogu nutné, v dnešním článku si ukážeme, jak můžeme
jednoduše složit jedno view z dalších nezávislých view a také to, že view nemusí být
jen stránka (Page), ale i “User Control”. Naše MainLoginView bude zobrazovat titulek
aplikace (Posterous klient), titulek stránky (Přihlášení) , ale textová pole “heslo”,
“uživatelské jméno” a tlačítko “Přihlásit" se” bude obsahovat “user control” LoginView,
který můžeme použít jako součást i zcela jiného view (stránky) v aplikaci.&amp;nbsp; Do
složky Views přidejte Windows Phone User Control a nazvěte jej LoginView.xaml. 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_15.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_6.png" width="244" height="170"&gt;&lt;/a&gt; 
&lt;p&gt;
Zkompilujte (Build) “solution”. 
&lt;p&gt;
Do view MainLoginView vložte tento kód: 
&lt;p&gt;
&lt;script src="http://gist.github.com/793080.js"&gt;&lt;/script&gt;
&lt;p&gt;
Jak jsem zmiňoval v &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;jednom
z předešlých článků&lt;/a&gt;, všechny stránky v aplikaci by měly být potomkem naší třídy &lt;a href="https://gist.github.com/763320"&gt;PageBase&lt;/a&gt;,
která je hostitelem pro view modely. Proto je naše stránka uzavřena v elementu &lt;em&gt;&amp;lt;controlex:PageBase&amp;gt;&lt;/em&gt;.&amp;nbsp;
XML jmenný prostor controleex je u mě namapován na xmlns:controlex="clr-namespace:RStein.PosterousReader.WP.UI".
V projektovém adresáři UI musíte mít tedy třídu PageBase.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_19.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_8.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Také v “code behind souboru” musíte třídu MainLoginView učinit potomkem PageBase.
&lt;/p&gt;
&lt;script src="https://gist.github.com/793085.js"&gt; &lt;/script&gt;
&lt;p&gt;
Hlavní xaml pro přihlášení uživatele obsahuje “User Control” LoginView, na který se
v MainLoginView odkazujeme. &lt;em&gt;(&amp;lt;views:LoginView Grid.Row="1"&amp;gt;&amp;lt;/views:LoginView&amp;gt;&lt;/em&gt;).&amp;nbsp;
XML jmenný prostor &lt;em&gt;views&lt;/em&gt; je mapován na jmenný prostor &lt;em&gt;RStein.PosterousReader.WP.Views &lt;/em&gt;v
C# (&lt;em&gt;xmlns:views="clr-namespace:RStein.PosterousReader.WP.Views&lt;/em&gt;) – v našem
případě tedy na projektový adresář Views.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_17.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_7.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Do view s názvem LoginView vložte následující XAML:
&lt;/p&gt;
&lt;script src="https://gist.github.com/793102.js"&gt; &lt;/script&gt;
&lt;p&gt;
Jak bylo vidět na snímku obrazovky na počátku článku, LoginView obsahuje hlavně textové
pole pro zadání jména uživatele (txtName) a prvek pro zadání hesla uživatele (txtPassword)
a tlačítko “Přihlásit se”. U prvků pro zadání uživatelského jména a hesla vás mohou
zarazit jen tagy &amp;lt;i:Interaction.Behaviors&amp;gt; a atributy &lt;em&gt;jako behaviors:TextboxPasswordAttachedProperties.TextBoxChangedAction&lt;/em&gt;,
jejichž význam vysvětlím za chvíli. Také vás hned&amp;nbsp; upozorním, že tlačítko “Přihlásit
se” je speciální tlačítko ((&lt;em&gt;&amp;lt;controlex:ButtonEx&lt;/em&gt;) dovolující reagovat na
stisknutí tlačítka uživatelem tak, že spustí metodu Execute objektu ICommand, což
standardní WP7 tlačítko nezvládá. Znovu&amp;nbsp; připomínám, že Silverlight ve WP7 je
bohužel založen na poměrně staré verzi 3 desktopového Silverlightu. Kód třídy ButtonEx
uvidíte také za chvíli.
&lt;/p&gt;
&lt;p&gt;
Máme view, ve view používáme “data binding”, ale nemáme ještě view modely, které fungují
pro view jako zdroj dat. 
&lt;p&gt;
&lt;strong&gt;V každém view modelu naší aplikace &lt;/strong&gt;budeme používat objekt &lt;em&gt;IPosterousApplication&lt;/em&gt; ke
komunikaci s Posterous, budeme chtít z view modelů navigovat na další view v aplikaci
a také bychom měli být schopni v každém view modelu získat&amp;nbsp; uživatelské jméno
a heslo zadané na na námi vytvářené přihlašovací obrazovce. To znamená, že společné
vlastnosti a služby view modelů pro naši aplikaci můžeme soustředit v bázové třídě
PosterousViewModelBase. Do projektové složky Views vložte novou třídu PosterousViewModelBase
a do ní zkopírujte následující kód. 
&lt;p&gt;
PosterousViewModelBase je potomkem &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;naší
staré známé třídy ViewModelBase&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793123.js"&gt;&lt;/script&gt;
&lt;p&gt;
V konstruktoru třída PosterousViewModelBase přijímá odkaz na objekt &lt;em&gt;IPosterousApplication&lt;/em&gt;,
který je základním rozcestnikem pro přístup k Posterous API, navigační službu &lt;em&gt;INavigationService&lt;/em&gt;,
která view modelu dovolí navigovat na další view v aplikaci&amp;nbsp; (např. ze seznamu
článků na detail vybraného článku), a titulek zobrazené stránky.&amp;nbsp; &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Titulek
převezme a nabízí poté ve vlastnosti PageTitle bázová třída ViewModelBase.&lt;/a&gt; 
&lt;p&gt;
Navigační služba je představována rozhraním &lt;em&gt;INavigationService.&lt;/em&gt; 
&lt;p&gt;
&lt;script src="http://gist.github.com/793126.js"&gt;&lt;/script&gt;
&lt;p&gt;
Základní implementace rozhraní &lt;em&gt;INavigationService&lt;/em&gt; pro WP7 je dostupná ve
třídě &lt;em&gt;DefaultWPNavigationService&lt;/em&gt; a pouze obaluje navigační služby dostupné
v samotných WP7 aplikacích. 
&lt;/p&gt;
&lt;script src="http://gist.github.com/793133.js"&gt;&lt;/script&gt;
&lt;p&gt;
Rozhraní &lt;em&gt;INavigationService&lt;/em&gt; i třídu &lt;em&gt;DefaultWPNavigationService&lt;/em&gt; vložte
do projektové složky HostServices.Více si o navigaci mezi různými view povíme v dalších
článcích.
&lt;/p&gt;
&lt;p&gt;
Vraťmě se k PosterousViewModelBase. V PosterousViewModelBase máme vždy uloženo ve
statických vlastnostech LastUsedUserName a LastUsedPassword poslední zadané přihlašovací
údaje, které může každý view model využít při získání nebo úpravě dat z Posterous. 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Poznámka: Kdyby někoho z vás pohoršovali statické vlastnosti, klidně si jako domácí
úkol napište “CredentialsManager”, který bude injektován stejně jako již zmíněné dvě
další služby do view modelů. Prozatím nechci komplikovat kód víc, než je nutné.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
My máme dvě view, MainLoginView a LoginView, a proto vytvoříme i dva view modely.
Opět zdůrazňuju, že tato volba je na vás &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;a
díky “dědění view modelů”&lt;/a&gt; bychom mohli ponechat třeba dvě view a vytvořit pro
ně jen jeden společný view model. 
&lt;p&gt;
Do projektové složky ViewModels přidejte třídu nazvanou MainLoginViewModel – view
model pro MainLoginView. &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;Název
view modelu nyní musí odpovídat konvenci “NázevView +ViewModel”. Zdůrazňuju i zde,
že jde jen o konvenci a že si můžete jednoduše napsat jiný IViewModelResolver, který
dohledá dle vašich zcela jiných projektových konvencí k view vhodný view model.&lt;/a&gt; 
&lt;p&gt;
MainLoginViewModel je sympaticky jednoduchý objekt. Má jen delegující konstruktor,
ve kterém předá své bázové třídě PosterousViewModelBase vyžadované povinné argumenty
posterousApplication, navigationService a titulek stránky. 
&lt;p&gt;
&lt;script src="http://gist.github.com/793149.js"&gt;&lt;/script&gt;
&lt;p&gt;
Texty v aplikaci nejsou prozatím lokalizovány a titulky stránek jsou uloženy ve třídě
GlobalConstants. Do “rootu” projektu přidejte třídu GlobalConstants.cs 
&lt;p&gt;
&lt;script src="http://gist.github.com/793153.js"&gt;&lt;/script&gt;
&lt;p&gt;
Název aplikace (APP_MAIN_TITLE) , podobně jako titulek stránky, &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;vydává
ve vlastnosti AppTitle&amp;nbsp; opět ViewModelBase&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Jen o trochu složitější bude view model pro LoginView. Do projektové složky ViewModels
přidejte třídu LoginViewModel. 
&lt;p&gt;
&lt;script src="http://gist.github.com/793171.js"&gt;&lt;/script&gt;
&lt;p&gt;
V LoginViewModelu máme opět delegující konstruktor, jedinou změnou oproti MainLoginViewModelu
je to, že jako titulek stránky předáváme prázdný řetězec, protože předpokládáme, že
titulek na stránku dodá “nadřízené” view.
&lt;/p&gt;
&lt;p&gt;
Vlastnosti a jejich význam
&lt;/p&gt;
&lt;table border="1" cellspacing="0" cellpadding="2" width="656"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="166"&gt;
&lt;strong&gt;Název vlastnosti&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="488"&gt;
&lt;strong&gt;Popis&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
TextChangedAction&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Akce, která má být vyvolána, když se ve view změní text přihlašovacího jména nebo
hesla. Tato akce je v konstruktoru inicializována tak, že si vynutíme opětovné vyhodnocení
toho, zda může být proveden LoginCommand. V článku popíšu, proč je to (prozatím?)
řešeno takto.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
LoginCommand&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Objekt podporující rozhraní ICommand,&amp;nbsp; který v metodě Execute zavolá metodu handleLogin.
Metoda handleLogin uloží zadané jméno a heslo do statických vlastností LastUsedPassword
a a LastUsedUserName a přesměruje uživatele na stránku se seznamem blogů. Instanční
vlastnost UserPassword je při každém pokusu o navigaci na stránku se seznamem blogů
“vyčištěna” tím, že je do ní uložen prázdný řetězec, a při návratu na přihlašovací
obrazovku tedy není automaticky předvyplněno heslo, což byl jeden z našich požadavků
na přihlašovací dialog.&lt;br&gt;
LoginCommand může být proveden jen tehdy, když bylo ve view zadáno a do view modelu
přes oboustranný (two way) binding zpropagováno uživatelské jméno a heslo. Pokud vlastnosti
UserName a UserPassword mají hodnotu null nebo obsahují prázdný řetězec, LoginCommand
nemůže být proveden.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
UserName&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Zadané přihlašovací jméno na službu Posterous. V &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;metodě
DoInternalInit, která je volána na začátku životního cyklu view modelu&lt;/a&gt; předvyplníme
uživatelské jméno posledním zadaným uživatelským jménem, které jsme dříve uložili
do statické vlastnosti LastUsedUserName.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="170"&gt;
UserPassword&lt;/td&gt;
&lt;td valign="top" width="484"&gt;
Heslo na službu Posterous.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
Co potřebujeme, abychom mohli náš LoginViewModel zkompilovat? 
&lt;p&gt;
Do třídy GlobalConstants přidejte URL dalšího view se seznamem blogů a článků. 
&lt;p&gt;
&lt;script src="http://gist.github.com/793195.js"&gt;&lt;/script&gt;
&lt;p&gt;
Stránku PostsListView.xaml vytvoříme v dalším článku, nyní ji celou vytvářet nemusíte.
Postačí do složky Views dát novou stránku (Page) s názvem PostsListView.xaml. 
&lt;p&gt;
Jak jsem již psal, ve WP7 nemáme bohužel podporu pro objekty ICommand. Třída DelegateCommand,
jejíž instancí je LoginCommand, &lt;strong&gt;je minimalistickou implementací &lt;/strong&gt;rozhraní
ICommand. 
&lt;p&gt;
Pokud podobnou třídu nemáte, vložte si&amp;nbsp; do projektu třídu DelegateCommand. U
mě je v jmenném prostoru &lt;strong&gt;RStein.PosterousReader.Common.&lt;/strong&gt; 
&lt;p&gt;
&lt;strong&gt;&lt;script src="http://gist.github.com/793206.js"&gt;&lt;/script&gt;&lt;/strong&gt; 
&lt;p&gt;
Třídě DelegateCommand můžete předat dva delegáty. Delegát executeAction (“co má být
vykonáno”) je spuštěn v metodě Execute z rozhraní ICommand. Delegát canExecuteAction
představuje implementaci metody CanExecute (“může být&amp;nbsp; nyní command vykonán?”).
Minimalistická implementace je to proto, že nijak nepoužívám událost CanExecuteChanged,
a namísto toho jsem si pro “binding” vystavil speciální vlastnost CanExecuteCommand,
která v get akcesoru deleguje na metodu CanExecute.
&lt;/p&gt;
&lt;p&gt;
Vlastnost TextChangedAction v LoginViewModelu je delegát typu Action, který nám pomáhá
vyřešit jeden z požadavků na přihlášení. 
&lt;p&gt;
&lt;em&gt;“Jestliže není uživatelské jméno vyplněno (prázdný řetězec) a/nebo není vyplněno
heslo, tlačítko Přihlásit se je neaktivní.”&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
To znamená, že potřebujeme po každém přidání nebo smazání znaku v textboxu pro zadání
jména uživatele i v textboxu pro zadání hesla zjišťovat, jestli můžeme ve view zpřístupnit
tlačítko pro přihlášení. Když je alespoň jeden textbox prázdný, tlačítko pro přihlášení
není dostupné, když je vyplněno alespoň jedním znakem jméno i heslo, tlačítko pro
přihlášení je dostupné.
&lt;/p&gt;
&lt;p&gt;
Jak je tento požadavek ve view a view modelu splněn?
&lt;/p&gt;
&lt;p&gt;
Ve view &lt;em&gt;LoginView&lt;/em&gt; je vlastnost &lt;em&gt;IsEnabled&lt;/em&gt; tlačítka “Přihlásit se“
z třídy &lt;em&gt;ButtonEx&lt;/em&gt; “nabindována” na vlastnost &lt;em&gt;CanExecuteCommand&lt;/em&gt; objektu &lt;em&gt;LoginCommand&lt;/em&gt; ve
view modelu.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_21.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_9.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Do projektové složky UI si přidejte třídu ButtonEx, která doplňuje standardní WP7
tlačítko o jednoduchou podporu objektů ICommand.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;&lt;script src="http://gist.github.com/793221.js"&gt;&lt;/script&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Vlastnost CanExecuteCommand musí vracet true, pokud je v každém textboxu alespoň jeden
znak, jinak false. Jak ale ve view modelu zjistíme, že uživatel zadal nebo smazal
v některém textovém poli další znak? Do view modelu se při oboustranném bindingu zpropaguje
hodnota z textového pole až po opuštění textového pole uživatelem, ale my přitom musíme
reagovat ve view modelu na zadání každého znaku.
&lt;/p&gt;
&lt;p&gt;
Takové chování textových polí ve WP7 skutečně nemáme a musíme si ho dopsat, a to nejlépe
za pomoci ”attached” vlastností a objektů &lt;em&gt;Behavior&amp;lt;T&amp;gt;&lt;/em&gt;. Nejprve se podívejme,
jak vypadají objekty TextBox a PasswordBox v XAMLu, když jsou rozšířeny o “attached”
vlastnost &lt;em&gt;TextboxPasswordAttachedProperties.TextBoxChangedAction&lt;/em&gt;, která je
“nabindována” na nám již známou vlastnost TextChangedAction typu Action ve view modelu.&amp;nbsp;
“Attached” vlastnost &lt;em&gt;TextBoxChangedAction&lt;/em&gt; tedy říká: “Hej, kdykoli se změní
u prvku zadaný text, musí NĚKDO ochotný zavolat delegáta TextChangedAction, abychom
ve view modelu nebyli odříznuti od novinek ve světě view.”
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_23.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_10.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
A ten někdo bude náš objekt Behavior , který zase světu sděluje: “Mám dobré vychování,
a když mi dovolíte vstoupit do bran tagu PasswordBox nebo TextBox, delegáta TextChangedAction
zavolám,&amp;nbsp; i když to sám WP7 TextBox a PasswordBox nezvládne.”
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793240.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Další nepříjemností ve WP7 je, že i když objekt Behavior má mít pro TextBox a PasswordBox&amp;nbsp;
stejné chování, musíme napsat dva objekty Behavior pro každý prvek, protože TextBox
ani PasswordBox spolu kupodivu nemají moc společného. My se alespoň pokusíme kód v
obou objektech Behavior neduplikovat.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Do projektové složky Behaviors přidejte třídu TextboxPasswordAttachedProperties a
v ní vytvořte attached vlastnost TextBoxChangedAction.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793248.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Do složky Behaviors přidejte abstraktní třídu TextChangedBehaviorBase, která bude
fungovat jako základ pro dva podobné objekty Behavior určené pro TextBox (TextBoxTextChangedUpdateSourceBehavior)
a PasswordBox (PasswordTextChangedBehavior). &lt;strong&gt;Do projektu musíte přidat referenci
na knihovnu System.Windows.Interactivity, &lt;/strong&gt;kterou naleznete většinou ve složce &lt;em&gt;c:\Program
Files\Microsoft SDKs\Expression\Blend\Windows Phone\v7.0\Libraries\System.Windows.Interactivity.dll. &lt;/em&gt;&lt;strong&gt;Bez
této knihovny není dostupná bázová třída Behavior&amp;lt;T&amp;gt;.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;script src="http://gist.github.com/793259.js"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Metoda RunTextChangedAction se pro objekt Textbox a PasswordBox asociovaný s tímto
objektem Behavior&amp;nbsp; pokusí dohledat a spustit delegáta v “attached” vlastnost
TextBoxChangedAction. Metoda UpdateSource požádá odvozené třídy o vydání "objektu
BindingExpression” voláním metody GetBindingExpression. Vrácený objekt “BindingExpression“
by měl&amp;nbsp; zapouzdřovat propojení vlastnosti view modelu (např UserName) s textem
v textovém poli. Po kontrole, že se jedná o oboustranný (two way) binding, metoda
UpdateSource zavolá na objektu BindingExpression UpdateSource, což způsobí přenesení
hodnoty zadané uživatelem v textovém poli ve view do zdrojové vlastnosti (např. UserName)
ve view modelu.
&lt;/p&gt;
&lt;p&gt;
Potomek TextBoxTextChangedUpdateSourceBehavior v metodě GetBindingExpression vrátí
BindingExpression pro svou vlastnost Text. V přepsané metodě OnAttached, která je
volána vždy, když je objekt Behavior asociován s textboxem, si přihlásíme odběr události
TextChanged TextBoxu a při každé změně textu voláme zděděné a výše popsané metody
UpdateSource a RunTextChangedAction. V metodě OnDetaching si nezapomeneme odběr události
TextChanged odhlásit.
&lt;/p&gt;
&lt;script src="http://gist.github.com/793285.js"&gt;&lt;/script&gt;
&lt;p&gt;
Pro PasswordBox máme dalšího potomka PasswordTextChangedBehavior, který se od třídy
TextBoxTextChangedUpdateSourceBehavior liší jen tím, že v metodě GetBindingExpression
vrací “BindingExpression” pro vlastnost Password a zadávaný text sleduje přes událost
PasswordChanged.
&lt;/p&gt;
&lt;script src="https://gist.github.com/793557.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
V LoginView si nezapomeňte zkontrolovat, že máte namapovány správně xml prefixy &lt;em&gt;behaviors&lt;/em&gt; a &lt;em&gt;i&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;na
správné jmenné prostory v C#, abyste mohli využívat novou attached vlastnost TextBoxChangedAction
a objekty TextBoxTextChangedUpdateSourceBehavior&amp;nbsp; a PasswordTextChangedBehavior.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;prostoryxmlns:behaviors="clr-namespace:RStein.PosterousReader.WP.Behaviors"&lt;br&gt;
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_25.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/image_thumb_11.png" width="244" height="154"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Dodejme, že náš delegát TextChangedAction ve view modelu simuluje změnu objektu LoginCommand,
který je přidružen k tlačítku Přihlásit se a tlačítko Přihlásit tedy po každém zadání
znaku zjistí, jestli má být dostupné.&amp;nbsp; Zopakujme, že vlastnost IsEnabled tlačítka
je “nabindována” na vlastnost LoginCommand.CanExecuteCommand. 
&lt;/p&gt;
&lt;p&gt;
Aplikaci můžete spustit.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Poznámka: Ještě si ale nezapomeňte do složky UIServices dát kód rozhraní IViewModelResolver
a třídy ViewModelResolver, které jsem popisoval v článku &lt;/em&gt;&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;&lt;em&gt;propojení
view modelu s view (stránkou)&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, protože bez třídy ViewModelResolver by
aplikace nebyla schopna pro naše MainLoginView a LoginView dohledat právě vytvořené
view modely. A v aplikaci musíte mít samozřejmě všechny další třídy z předchozích
článků, které jsou odpovědné za “tombstoning” apod.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
U aplikace si můžete zkontrolovat, že:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Přihlašovací dialog plní všechny požadavky, které jsme vypsal&amp;nbsp; na začátku článku.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;
&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Nemusíme se nijak starat o “tombstoning” aplikace. Zmáčkněte tlačítko Win, poté se
tlačítkem Back vraťte do aplikace a všechny hodnoty v textových polích zůstanou zachovány.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Tlačítko pro přihlášení je dostupné jen tehdy, když textová pole pro zadání jména
a hesla jsou vyplněna. Pokud alespoň jedno pole vyplněno není, tlačítko je neaktivní.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
I naše minimalistická podpora rozhraní ICommand vede k tomu, že ve View nemáme žádný&amp;nbsp;
“code behind”. Logika stojící za view je jen ve view modelech a XAML tahá data z view
modelů přes “data binding”. Pokud přesně tohle to považujete za důležité, budete určitě
nadšeni. Jak uvidíte v dalších článcích, já jsem vůči strategii “vše do XAMLu” hodně
skeptický, ale XAML puristé &lt;strike&gt;si &lt;/strike&gt;mohou jít po dnešku jistě &lt;strike&gt;ožrat
držku &lt;/strike&gt;slavit&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
I když šlo jen o přihlašovací formulář, vytvořili jsme si další skládací kostky (attached
vlastnosti, Behavior, PosterousViewModelBase), které se nám budou hodit při psani
dalších view a view modelů (nejen)&amp;nbsp; v této aplikaci.&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Zauvažujte nad tím, jestli by se nám také nehodila nějaká podpora ve view modelech
pro ukládání nejen tranzientního stavu, ale i pro ukládání “trvalejšího” stavu, který
bude dostupný i v další nezávislé instanci aplikace. Možná by stálo za to, aby si
aplikace pamatovala poslední zadané přihlašovací jméno nejen při “tombstoningu”, ale
aby přihlašovací jméno bylo nabídnuto i při novém spuštění aplikace. A z hlediska
vývojáře&amp;nbsp; bezbolestná podpora pro ukládání perzistentního stavu (&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;data
s “delší záruční lhůtou”&lt;/a&gt;) bude námětem dalšího WP7 intermezza. Doufám, že se těšíte. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-V--vyt_92C1/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Předchozí články:&lt;br&gt;
&lt;br&gt;
&lt;/strong&gt;&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt; 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx"&gt;Tipy
pro Windows Phone 7 aplikace III–propojení view modelu s view (stránkou)&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IV+Intermezzo+I+Zjednoduscaronenaacute+Registrace+Serializovatelnyacutech+T%c5%99iacuted+Nesouciacutech+Tranzientniacute+Stav+V+KnownTypesDictionary.aspx"&gt;Tipy
pro Windows Phone 7 aplikace IV - intermezzo I - zjednodušená registrace serializovatelných
tříd nesoucích tranzientní stav v KnownTypesDictionary&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=1ab0ecc7-7a79-4e17-b2f8-358bd7713695" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,1ab0ecc7-7a79-4e17-b2f8-358bd7713695.aspx</comments>
      <category>C# Posterous API</category>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=38539832-2f1d-42cf-8549-b59697b093c4</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=38539832-2f1d-42cf-8549-b59697b093c4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <em>
            <font color="#ff0000">Update 4. 1.   2011  - upraven kód objektu
UIHelper a spolupracující metody tak, aby byl klíč generovaný pro tranzientní stav
každého view modelu skutečně unikátní.</font>
          </em>
          <font color="#ff0000">Když rozkliknete
GISTy, můžete se podívat i na původní verzi kódu.</font>
        </p>
        <p>
V <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">předchozím
článku</a> jsme se podrobně věnovali vytvoření bázové třídy pro view modely včetně
podpory ukládání tranzientního stavu během “tombstoningu” a na konci jsem slíbil,
že další díl bude věnován hlavně propojení našich view modelů s view. 
</p>
        <p>
View pro nás bude hostitel view modelu a v souladu s WP7 modelem navigace mezi jednotlivými
stránkami budeme za hlavního hostitele považovat potomka třídy <em>PhoneApplicationPage<strong>. </strong></em>Uvidíme
ale, že při vytváření View nejsme omezeni na potomky <em>PhoneApplicationPage, </em>protože
budeme schopni vytvořit i view jako potomka třídy <em>UserControl.</em></p>
        <p>
Zrekapitujme hlavní funkce, které by měl náš hostitel view modelů zvládat: 
</p>
        <ol>
          <li>
Při vytvoření stránky je třeba najít ke stránce přidružený view model. Dodejme již
nyní, že povinností hostitele bude dohledat i vnořené (dceřiné) view modely, jestliže
je jedna stránka složena z více nezávislých view a každé view může být asociováno
s jiným view modelem.<br /><br /></li>
          <li>
Při vytvoření stránky je nutné u view modelu volat metodu <em>Init</em> pro základní
inicializaci view modelu, jestliže view model podporuje naše rozhraní <em>IInittialize<strong>. </strong></em>Znovu
připomínám, co zaznělo v <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">minulém
článku</a>, že si implementaci žádných rozhraní u view modelů nevynucujeme.<br /><br /></li>
          <li>
Jestliže se stránka stane poprvé nebo po návratu uživatele “aktivní” (zobrazenou),
je nutné volat na view modelu metodu <em>Activate</em>, když view model podporuje
rozhraní <em>IActivated.<br /><br /></em>. 
</li>
          <li>
Jestliže uživatel ze stránky odchází, hostitel na view modelu volá metodu Deactivate
z rozhraní IDeactivated.<br /><br /></li>
          <li>
Hostitel musí být schopen při “tombstoningu” uložit tranzientní stav view modelu.<br /><br /></li>
          <li>
Po návratu z “tombstoningu” hostitel dovolí view modelu obnovit tranzientní stav.<br /><br /></li>
          <li>
            <strong>Hostitel se nás bude snažit ve view modelech odstínit od všech  WP7 nedomyšleností,
záludností, nesmyslných omezení a programátorských vrtochů, které jsou nedílnou a
z pohledu mobilní MS divize jistě i zábavnou součástí celkově kapriciozního životního
cyklu třídy PhoneApplicationPage.<br /></strong>
          </li>
        </ol>
        <p>
Nyní již můžeme přístoupit k vytvoření hostitele. Našim hostitelem bude třída <em>PageBase, </em>která
je potomkem PhoneApplicationPage z WP7 frameworku. Nakonec jsem pro účely článku zvolil
toto řešení, i když není problém v dalších dílech ukázat adaptér, který nás nutnosti
vlastní stránky v aplikaci odvozovat z bázové třídy <em>PageBase</em> zbaví. Myslím
si ale, že navigační model WP7 aplikací neposkytuje sám o sobě mnoho prostoru pro
kreativitu, a proto nutnost dědit z PageBase místo třídy PhoneApplicationPage z WP7
za nějak zvlášť restriktivní nepovažuju.
</p>
        <p>
Třída PageBase:
</p>
        <script src="https://gist.github.com/763320.js">
        </script>
        <p>
Kdykoli  dojde k aktivaci stránky, čímž míním první navigaci na stránku, nebo
návrat na stránku pomocí tlačítka Back, je volána metoda <em>OnNavigatedTo. </em>My
jsme přepsali metodu OnNavigatedTo a v ní vždy nastavíme svou vlastnost WasLayoutUpdateCalled
na false. <strong>Vlastnost WasLayoutUpdateCalled použijeme za chvíli, zde jen řekněme,
že tuto vlastnost potřebujeme k tomu, abychom poznali, že již je vytvořen celý vizuální
strom ovládacích prvků a že můžeme s ovládacími prvky bez obav pracovat. </strong>Bohužel
v metodě OnNavigatedTo vizuální strom prvků vytvořen být nemusí. O některých problémech,
které je nutné řešit, když není zcela vytvořen vizuální strom prvků, jsem již mluvil
u ovládacího prvku <em>WebBrowser </em>v <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">první
části tohoto seriálu</a>. 
</p>
        <p>
Metoda OnNavigatedTo také dá příkaz k vyzvednutí dříve uloženého tranzientního stavu
pomocí metody loadSavedTransientState z vlastnosti PhoneApplicationPage.State. Tranzientní
stav, pokud existuje, je pouze uložen do vlastnosti LastSavedTransientState a zatím
se s ním nijak nepracuje. Klíčem, pod kterým je uložen stav celé stránky včetně tranzientního
stavu view modelů, je plně kvalifikované jméno aktuální stránky (string stateKey =
GetType().FullName). <strong>Měli bychom si být vědomi, že při této implementaci nesmíme
mít jednu stránku v aplikaci nahranou vícekrát, protože by různé instance stejné stránky
mezi sebou sdílely stav. Když budete trvat na tom, že jedna stránka může mít v systému
několik instancí, není problém změnit generování klíče, pod kterým bude stav pro každou
unikátně identifikovanou instanci uložen.</strong></p>
        <script src="https://gist.github.com/763335.js">
        </script>
        <p>
Pokračujme v našem scénáři. V konstruktoru si přihlašujeme odběr události LayoutUpdated
(<em>LayoutUpdated += PageBase_LayoutUpdated;)<strong>, </strong></em>abychom byli
notifikováni, že již můžeme bezpečně pracovat s ovládacími prvky.
</p>
        <p>
 
</p>
        <p>
Obslužná metoda <em>handleLayoutUpdated</em> je po každé navigaci na stránku spouštěna 
jen jednou, a proto se podíváme na hodnotu vlastnosti  WasLayoutUpdateCalled
– jestliže má hodnotu true, nic dalšího neděláme. <strong>Jinak metoda zkontroluje,
zda instance PageBase je nově vytvořena, k čemuž dojde při první navigaci na stránku
a také po obnovení z “tombstonovaného" stavu. Jinak řečeno – když je volán konstruktor
třídy PageBase, znamená to, že máme stránku v “panenském” stavu, protože v ní nejsou
žádná data a dokonce ani nebyly připojeny view modely. A proto bezparametrický konstruktor
PageBase nastavuje vlastnost IsNewInstance na true, abychom v metodě <em>handleLayoutUpdated</em> 
věděli, že máme co do činění s novou instancí stránky. U nové stránky je třeba získat
view modely, a pokud je stránka obnovena po “tombstoningu”, je třeba do view modelů
nahrát tranzientní stav.  Při variantě “nová instance stránky” metoda <em>handleLayoutUpdated</em> volá
metodu LoadState.</strong></p>
        <p>
Jestliže nebyl volán konstruktor a stránka obsahuje veškerý stav, k čemuž většinou
dojde, když se vrátíme bez “tombstoningu” pomocí tlačítka Back na stránku, metoda <em>handleLayoutUpdated</em> volá
pouze pomocnou metodu <em>handleAllActivated, </em>která proiteruje všechny dříve
nahrané view modely, a když podporují rozhraní <em>IActivated</em>, tak na nich zavolá
metodu <em>Activate</em>.
</p>
        <script src="https://gist.github.com/763340.js">
        </script>
        <p>
Metoda <em>LoadState</em> ihned deleguje na metodu <em>restoreTransientState</em>,
jíž předá v objektu ElementIndexPair odkaz na aktuální stránku (this), která představuje
“root” všech prvků, a relativní index nastavený na 0 (první prvek na této úrovni).
V dalším argumentu jako prvek, pro který má být obnoven stav, předá opět odkaz na
aktuální stránku (this) a poslední argument, ve kterém metoda <em>restoreTransientState</em> očekává
naposledy použitý view model, je null, protože se žádnými view modely se ještě nepracuje.
</p>
        <p>
Metoda <em>restoreTransientState</em> nejprve zkontroluje, jestli předaný ovládací
prvek představuje View. K tomu použije objekt podporující rozhraní IViewModelResolver,
který je uložen ve statické vlastnosti ViewModelManager. Přesněji řečeno, ve vlastnosti
ViewModelManager můžete uložit delegáta (<em>Func<iviewmodelresolver>
)
</iviewmodelresolver></em>, který vrací objekt realizující rozhraní IViewModelResolver.
Ve statickém konstruktoru třídy PageBase ukládám do vlastnosti ViewModelManager funkci,
která vytváří v mé aplikaci výchozí IViewModelResolver s názvem ViewModelResolver
(<em>ViewModelManager = () =&gt; new ViewModelResolver();)</em></p>
        <p>
Rozhraní IViewModelResolver
</p>
        <p>
          <script src="https://gist.github.com/763365.js">
          </script>
        </p>
        <p>
Metodě IsView předáte vybraný objekt a ona vám vrátí true, jestliže objekt považuje
za view, pro které by měl existovat view model. Metoda ResolveViewModel přijme objekt
představující view a dohledá k němu view model.
</p>
        <p>
Pro lepší představu vám mohu bez podrobnějšího komentáře ukázat třídu, která v aplikaci
používající Posterous API dohledá k view view model na základě jmenné konvence. Za
View se považuje každá instance z třídy, jejíž název končí znaky “View”, a k tomuto
View je vrácen view model, který se jmenuje stejně jako view, ale končí znaky “ViewModel”.
K view s názvem Login<em>View </em>je tedy vrácen view model s názvem Login<em>ViewModel.</em></p>
        <script src="https://gist.github.com/763375.js">
        </script>
        <p>
Vraťme se k metodě restoreTransientState. Když metoda zjistí, že objekt představuje
view, pokusí se dohledat dříve uložený tranzientní stav. Stav je uložen pro každé
view v objektu IDictionary, konkrétně v třídě KnownTypesDictionary, pod klíčem, kterým
je úplné jméno ovládacího prvku – úplným jménem se rozumí jméno třídy ovládacího prvku
+ jména tříd všech jeho vizuálních předků (<em>ancestors</em>). Ke jménu třídy každého
prvku je přidán pořadový indexu prvku mezi prvky na stejné úrovni vizuálního stromu.
Klíč generuje třída UIHelper v metodě GetTransientStateKey.
</p>
        <p>
          <script src="https://gist.github.com/763381.js">
          </script>
Metoda restoreTransientState se poté s s využitím metody prepareViewModel pokusí získat
přes ViewModelManager view model (<em>ViewModelManager().ResolveViewModel(obj</em>),
dále zjistí, jestli view model podporuje rozhraní ITransientStateManager, IInitialize
a a IActivated a pokračuje takto:
</p>
        <ol>
          <li>
Jestliže máme uložen tranzientní stav (došlo k “tombstoningu”) a view model podporuje
rozhraní ITransientStateManager, zavoláme metodu LoadState z rozhraní ITransientStateManager
(<em>stateManager.LoadState(LastSavedTransientState[stateKey]); </em>a view model
tak dostane šanci načíst dříve uložená tranzientní data.<br /><br /></li>
          <li>
Když nemáme uložen tranzientní stav a view model podporuje rozhraní IInitialize, zavoláme
metodu IInitialize.Init. View model tak dostane šanci nahrát data, ať už se souboru,
z webové služby nebo jiného datového zdroje, která mají být zobrazena v aktuálním
view.<br /></li>
        </ol>
        <p>
Poté, co view model obnoví nebo inicializuje svůj stav, je volána metoda activateAndSetDataContext,
která na view modelech podporujících rozhraní IActivated zavolá metodu Activate a
nastaví view model jako datový zdroj (“DataContext”) view.
</p>
        <p>
Nakonec pro všechny dceřiné prvky, které mohou představovat vnořená view (např. user
control), rekurzivně zavoláme opět metodu restoreTransientState. K získání dceřiných
prvků a jejich relativního indexu mezi prvky na stejné úrovni zanoření ve vizuálním
stromu je použita metoda UIHelper.GetChildren.
</p>
        <script src="https://gist.github.com/763405.js">
        </script>
        <p>
Metoda LoadState, restoreTransientState a další pomocné metody, o kterých jsme mluvili
v předchozích odstavcích:
</p>
        <script src="https://gist.github.com/763410.js">
        </script>
        <p>
Za povšimnutí stojí ve scénáři metody restoreTransientState ještě několik dalších
věcí:
</p>
        <ul>
          <li>
Když zjišťujeme, jestli objekt podporuje rozhraní IInitialize (metoda <em>getInitObjectWithSyncContext</em>),
ihned do view modelu zpropagujeme synchronizační kontext (<em>initObject.SynchContext
= SynchronizationContext.Current</em>;), aby například událost PropertyChanged mohla
být vyvolávána vždy v UI vláknu.<br /><br /></li>
          <li>
Pomocná metoda <em>selectViewModel(frameworkElement, lastViewModel, currentViewModel);</em> odpovědná
za výběr view modelu zajistí, že když IViewModelResolver nenalezne pro view žádný
view model, automaticky view přiřadí view model použitý u předchozího view. Kdy to
potřebujete? Třeba když stránku rozdělíte na několik nezávislých “user controls”,
tak se můžete rozhodnout, jestli bude mít každý user control (view) svůj view model,
nebo view model vytvoříte jen pro celou stránku a “user controls” view modely automaticky
“zdědí”. To byl jen jeden příklad - úroveň zanoření view je zcela ve vaší režii. Slovo
“zdědí” je v uvozovkách, protože nejde o klasické dědení DataContextu, ale k předání
posledně použitého view modelu dojde i tehdy, když dvě view nemají společné “nadview”.<br /></li>
        </ul>
        <p>
          <em>Poznámka: Nejprve jsem chtěl volání metod Init a LoadState na view modelech a
následné nastavení DataContextu u view dát do jiného vlákna. Problém je v tomto případě
s dědením view modelů. Když přiřadíte view model, na kterém jste zavolali asynchronně
metodu Init, dalšímu vnořenému View, tak se může stát, že metoda Init ještě nedoběhla,
view model u prvního view nastaven není, ale u vnořeného (druhého) view již nastaven
je, což může vést k podivným a kvůli použití více vláken obtížně reprodukovatelným
chybám. Za asynchronní zpracování časově náročných scénářů zodpovídají samotné view
modely, které by měly přepisovat virtuální metodu DoInternalAsyncInit z ViewModelBase.
Metodu DoInternalAsyncInit jsem <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">popisoval
v předchozím článku</a>.</em>
        </p>
        <p>
Viděli jsme, kdy hostitel volá metody Init, Activate a kdy voláním metody LoadState
obnoví tranzientní stav ve view modelech. Ještě nám zbývá projít, kdy ukládáme tranzientní
stav a kdy notifikujeme view modely voláním jejich metody Deactivate o tom, že k nim
přidružené view (stránka) není již aktivní.
</p>
        <p>
          <strong>Nebudeme při ukládání tranzientního stavu nijak pátrat, jestli došlo k “tombstoningu”,
ale stav view modelů do <em>PhoneApplicationPage.State</em> uložíme vždy, když dojde
k opuštění stránky. Hlavním důsledkem tohoto rozhodnutí je, že s obsluhou metod 
Application_Launching, Application_Activated, Application_Deactivated a Application_Closing,
kterou jsem popisoval minule, se nemusíte kvůli “tombstoningu” trápit a zmíněné metody
můžete většinou zcela ignorovat.</strong>
        </p>
        <p>
O opuštění stránky jsm informováni v metodě OnNavigatedFrom, kterou přepíšeme. Metoda
OnNavigatedFrom voláním metody SaveState uloží stav všech view modelů a poté metoda
handleAllDeactivated na všech modelech  podporujících rozhraní IDeactivated zavolá
metodu Deactivate.
</p>
        <script src="https://gist.github.com/763441.js">
        </script>
        <p>
Popisovat kompletně logiku v metodě SaveState nemá smysl, protože tato metoda je reverzní
k metodě LoadState. Pro všechny view rekurzivně vyhledá jejich view modely a dovolí
jim uložit pod unikátním klíčem view, který je vygenerován třídou UIHelper, tranzientní
stav. Ten samý tranzientní stav view modelů, jehož obnovení v metodě LoadState jsem
popisoval výše.  <script src="https://gist.github.com/763445.js"></script></p>
        <p>
Za komentář stojí, že podmínka if<em> (stateManager != null &amp;&amp; stateManager
!= lastDataContext) </em>ošetřuje, abychom neukládali trazientní stav view modelu,
který slouží jako DataContext u více View, opakovaně, ale vždy pouze jednou.
</p>
        <p>
Tranzientní stav všech view modelů je ukládán do speciálního objektu Dictionary s
názvem KnownTypesDictionary.
</p>
        <p>
          <em>var statebag = new KnownTypesDictionary();</em>
        </p>
        <p>
Připomínám, že při tombstoningu je možné uložit jen serializovatelné objekty. Představme
si nyní, že KnownTypesDictionary je potomek třídy  Dictionary&lt;string, object&gt;.
Do takového objektu Dictionary můžeme vložit kteroukoli instanci z třídy, která je
přímo či nepřimo potomkem třídy Object, ale při pokusu o serializaci dostaneme chybu,
protože naše potomky DataContractSerializer nezná a očekává, že v kolekci budou jen
instance třídy Object, a ne instance odvozených tříd. Pomocí atributu <a href="http://msdn.microsoft.com/en-gb/library/system.runtime.serialization.knowntypeattribute.aspx">KnownType</a>,
který je aplikován na KnownTypesDictionary, můžeme DataContractSerializer informovat,
které všechny třídy má v objektu Dictionary očekávat. Jednou z  možností, jak
to udělat, je předat atributu KnownType název statické metody, která seznam “známých”
tříd vrací. 
</p>
        <p>
Dnes si ukážeme jednoduchou verzi třídy  <em>KnownTypesDictionary</em>, která
v metodě GetKnownTypes vrátí fixní seznam "známých” tříd. Příště si ukážeme, jak budou
“známé” třídy dohledány a registrovány  automaticky bez nutnosti vytvářet seznam
známých tříd vždy znovu a “natvrdo” v každé aplikaci. V dalších dílech také zjistíme,
jak právě vytvořená infrastruktura nám dovolí vytvářet WP7 aplikace příslovečným lusknutím
prstu, tedy spíš nečetným lusknutím prstů o klávesnici. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/8b4a80e9bf58_926F/wlEmoticon-smile_2.png" /><script src="https://gist.github.com/763469.js"></script></p>
        <p>
.
</p>
        <p>
 
</p>
        <p>
Předcházející články: 
</p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx">Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=38539832-2f1d-42cf-8549-b59697b093c4" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace III&amp;ndash;propojen&amp;iacute; view modelu s view (str&amp;aacute;nkou)</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+IIIndashpropojeniacute+View+Modelu+S+View+Straacutenkou.aspx</link>
      <pubDate>Mon, 03 Jan 2011 14:46:50 GMT</pubDate>
      <description>&lt;p&gt;
&lt;em&gt;&lt;font color="#ff0000"&gt;Update 4. 1.&amp;nbsp;&amp;nbsp; 2011&amp;nbsp; - upraven kód objektu
UIHelper a spolupracující metody tak, aby byl klíč generovaný pro tranzientní stav
každého view modelu skutečně unikátní.&lt;/font&gt;&lt;/em&gt; &lt;font color="#ff0000"&gt;Když rozkliknete
GISTy, můžete se podívat i na původní verzi kódu.&lt;/font&gt; 
&lt;p&gt;
V &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;předchozím
článku&lt;/a&gt; jsme se podrobně věnovali vytvoření bázové třídy pro view modely včetně
podpory ukládání tranzientního stavu během “tombstoningu” a na konci jsem slíbil,
že další díl bude věnován hlavně propojení našich view modelů s view. 
&lt;p&gt;
View pro nás bude hostitel view modelu a v souladu s WP7 modelem navigace mezi jednotlivými
stránkami budeme za hlavního hostitele považovat potomka třídy &lt;em&gt;PhoneApplicationPage&lt;strong&gt;. &lt;/strong&gt;&lt;/em&gt;Uvidíme
ale, že při vytváření View nejsme omezeni na potomky &lt;em&gt;PhoneApplicationPage, &lt;/em&gt;protože
budeme schopni vytvořit i view jako potomka třídy &lt;em&gt;UserControl.&lt;/em&gt; 
&lt;p&gt;
Zrekapitujme hlavní funkce, které by měl náš hostitel view modelů zvládat: 
&lt;ol&gt;
&lt;li&gt;
Při vytvoření stránky je třeba najít ke stránce přidružený view model. Dodejme již
nyní, že povinností hostitele bude dohledat i vnořené (dceřiné) view modely, jestliže
je jedna stránka složena z více nezávislých view a každé view může být asociováno
s jiným view modelem.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Při vytvoření stránky je nutné u view modelu volat metodu &lt;em&gt;Init&lt;/em&gt; pro základní
inicializaci view modelu, jestliže view model podporuje naše rozhraní &lt;em&gt;IInittialize&lt;strong&gt;. &lt;/strong&gt;&lt;/em&gt;Znovu
připomínám, co zaznělo v &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;minulém
článku&lt;/a&gt;, že si implementaci žádných rozhraní u view modelů nevynucujeme.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jestliže se stránka stane poprvé nebo po návratu uživatele “aktivní” (zobrazenou),
je nutné volat na view modelu metodu &lt;em&gt;Activate&lt;/em&gt;, když view model podporuje
rozhraní &lt;em&gt;IActivated.&lt;br&gt;
&lt;br&gt;
&lt;/em&gt;. 
&lt;li&gt;
Jestliže uživatel ze stránky odchází, hostitel na view modelu volá metodu Deactivate
z rozhraní IDeactivated.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Hostitel musí být schopen při “tombstoningu” uložit tranzientní stav view modelu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Po návratu z “tombstoningu” hostitel dovolí view modelu obnovit tranzientní stav.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
&lt;strong&gt;Hostitel se nás bude snažit ve view modelech odstínit od všech&amp;nbsp; WP7 nedomyšleností,
záludností, nesmyslných omezení a programátorských vrtochů, které jsou nedílnou a
z pohledu mobilní MS divize jistě i zábavnou součástí celkově kapriciozního životního
cyklu třídy PhoneApplicationPage.&lt;br&gt;
&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Nyní již můžeme přístoupit k vytvoření hostitele. Našim hostitelem bude třída &lt;em&gt;PageBase, &lt;/em&gt;která
je potomkem PhoneApplicationPage z WP7 frameworku. Nakonec jsem pro účely článku zvolil
toto řešení, i když není problém v dalších dílech ukázat adaptér, který nás nutnosti
vlastní stránky v aplikaci odvozovat z bázové třídy &lt;em&gt;PageBase&lt;/em&gt; zbaví. Myslím
si ale, že navigační model WP7 aplikací neposkytuje sám o sobě mnoho prostoru pro
kreativitu, a proto nutnost dědit z PageBase místo třídy PhoneApplicationPage z WP7
za nějak zvlášť restriktivní nepovažuju.
&lt;/p&gt;
&lt;p&gt;
Třída PageBase:
&lt;/p&gt;
&lt;script src="https://gist.github.com/763320.js"&gt; &lt;/script&gt;
&lt;p&gt;
Kdykoli&amp;nbsp; dojde k aktivaci stránky, čímž míním první navigaci na stránku, nebo
návrat na stránku pomocí tlačítka Back, je volána metoda &lt;em&gt;OnNavigatedTo. &lt;/em&gt;My
jsme přepsali metodu OnNavigatedTo a v ní vždy nastavíme svou vlastnost WasLayoutUpdateCalled
na false. &lt;strong&gt;Vlastnost WasLayoutUpdateCalled použijeme za chvíli, zde jen řekněme,
že tuto vlastnost potřebujeme k tomu, abychom poznali, že již je vytvořen celý vizuální
strom ovládacích prvků a že můžeme s ovládacími prvky bez obav pracovat. &lt;/strong&gt;Bohužel
v metodě OnNavigatedTo vizuální strom prvků vytvořen být nemusí. O některých problémech,
které je nutné řešit, když není zcela vytvořen vizuální strom prvků, jsem již mluvil
u ovládacího prvku &lt;em&gt;WebBrowser &lt;/em&gt;v &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;první
části tohoto seriálu&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
Metoda OnNavigatedTo také dá příkaz k vyzvednutí dříve uloženého tranzientního stavu
pomocí metody loadSavedTransientState z vlastnosti PhoneApplicationPage.State. Tranzientní
stav, pokud existuje, je pouze uložen do vlastnosti LastSavedTransientState a zatím
se s ním nijak nepracuje. Klíčem, pod kterým je uložen stav celé stránky včetně tranzientního
stavu view modelů, je plně kvalifikované jméno aktuální stránky (string stateKey =
GetType().FullName). &lt;strong&gt;Měli bychom si být vědomi, že při této implementaci nesmíme
mít jednu stránku v aplikaci nahranou vícekrát, protože by různé instance stejné stránky
mezi sebou sdílely stav. Když budete trvat na tom, že jedna stránka může mít v systému
několik instancí, není problém změnit generování klíče, pod kterým bude stav pro každou
unikátně identifikovanou instanci uložen.&lt;/strong&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/763335.js"&gt; &lt;/script&gt;
&lt;p&gt;
Pokračujme v našem scénáři. V konstruktoru si přihlašujeme odběr události LayoutUpdated
(&lt;em&gt;LayoutUpdated += PageBase_LayoutUpdated;)&lt;strong&gt;, &lt;/strong&gt;&lt;/em&gt;abychom byli
notifikováni, že již můžeme bezpečně pracovat s ovládacími prvky.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Obslužná metoda &lt;em&gt;handleLayoutUpdated&lt;/em&gt; je po každé navigaci na stránku spouštěna&amp;nbsp;
jen jednou, a proto se podíváme na hodnotu vlastnosti&amp;nbsp; WasLayoutUpdateCalled
– jestliže má hodnotu true, nic dalšího neděláme. &lt;strong&gt;Jinak metoda zkontroluje,
zda instance PageBase je nově vytvořena, k čemuž dojde při první navigaci na stránku
a také po obnovení z “tombstonovaného" stavu. Jinak řečeno – když je volán konstruktor
třídy PageBase, znamená to, že máme stránku v “panenském” stavu, protože v ní nejsou
žádná data a dokonce ani nebyly připojeny view modely. A proto bezparametrický konstruktor
PageBase nastavuje vlastnost IsNewInstance na true, abychom v metodě &lt;em&gt;handleLayoutUpdated&lt;/em&gt;&amp;nbsp;
věděli, že máme co do činění s novou instancí stránky. U nové stránky je třeba získat
view modely, a pokud je stránka obnovena po “tombstoningu”, je třeba do view modelů
nahrát tranzientní stav.&amp;nbsp; Při variantě “nová instance stránky” metoda &lt;em&gt;handleLayoutUpdated&lt;/em&gt; volá
metodu LoadState.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Jestliže nebyl volán konstruktor a stránka obsahuje veškerý stav, k čemuž většinou
dojde, když se vrátíme bez “tombstoningu” pomocí tlačítka Back na stránku, metoda &lt;em&gt;handleLayoutUpdated&lt;/em&gt; volá
pouze pomocnou metodu &lt;em&gt;handleAllActivated, &lt;/em&gt;která proiteruje všechny dříve
nahrané view modely, a když podporují rozhraní &lt;em&gt;IActivated&lt;/em&gt;, tak na nich zavolá
metodu &lt;em&gt;Activate&lt;/em&gt;.
&lt;/p&gt;
&lt;script src="https://gist.github.com/763340.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda &lt;em&gt;LoadState&lt;/em&gt; ihned deleguje na metodu &lt;em&gt;restoreTransientState&lt;/em&gt;,
jíž předá v objektu ElementIndexPair odkaz na aktuální stránku (this), která představuje
“root” všech prvků, a relativní index nastavený na 0 (první prvek na této úrovni).
V dalším argumentu jako prvek, pro který má být obnoven stav, předá opět odkaz na
aktuální stránku (this) a poslední argument, ve kterém metoda &lt;em&gt;restoreTransientState&lt;/em&gt; očekává
naposledy použitý view model, je null, protože se žádnými view modely se ještě nepracuje.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;restoreTransientState&lt;/em&gt; nejprve zkontroluje, jestli předaný ovládací
prvek představuje View. K tomu použije objekt podporující rozhraní IViewModelResolver,
který je uložen ve statické vlastnosti ViewModelManager. Přesněji řečeno, ve vlastnosti
ViewModelManager můžete uložit delegáta (&lt;em&gt;Func&lt;iviewmodelresolver&gt;
)
&lt;/em&gt;, který vrací objekt realizující rozhraní IViewModelResolver. Ve statickém konstruktoru
třídy PageBase ukládám do vlastnosti ViewModelManager funkci, která vytváří v mé aplikaci
výchozí IViewModelResolver s názvem ViewModelResolver (&lt;em&gt;ViewModelManager = () =&amp;gt;
new ViewModelResolver();)&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Rozhraní IViewModelResolver
&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/763365.js"&gt; &lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Metodě IsView předáte vybraný objekt a ona vám vrátí true, jestliže objekt považuje
za view, pro které by měl existovat view model. Metoda ResolveViewModel přijme objekt
představující view a dohledá k němu view model.
&lt;/p&gt;
&lt;p&gt;
Pro lepší představu vám mohu bez podrobnějšího komentáře ukázat třídu, která v aplikaci
používající Posterous API dohledá k view view model na základě jmenné konvence. Za
View se považuje každá instance z třídy, jejíž název končí znaky “View”, a k tomuto
View je vrácen view model, který se jmenuje stejně jako view, ale končí znaky “ViewModel”.
K view s názvem Login&lt;em&gt;View &lt;/em&gt;je tedy vrácen view model s názvem Login&lt;em&gt;ViewModel.&lt;/em&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/763375.js"&gt; &lt;/script&gt;
&lt;p&gt;
Vraťme se k metodě restoreTransientState. Když metoda zjistí, že objekt představuje
view, pokusí se dohledat dříve uložený tranzientní stav. Stav je uložen pro každé
view v objektu IDictionary, konkrétně v třídě KnownTypesDictionary, pod klíčem, kterým
je úplné jméno ovládacího prvku – úplným jménem se rozumí jméno třídy ovládacího prvku
+ jména tříd všech jeho vizuálních předků (&lt;em&gt;ancestors&lt;/em&gt;). Ke jménu třídy každého
prvku je přidán pořadový indexu prvku mezi prvky na stejné úrovni vizuálního stromu.
Klíč generuje třída UIHelper v metodě GetTransientStateKey.
&lt;/p&gt;
&lt;p&gt;
&lt;script src="https://gist.github.com/763381.js"&gt; &lt;/script&gt;
Metoda restoreTransientState se poté s s využitím metody prepareViewModel pokusí získat
přes ViewModelManager view model (&lt;em&gt;ViewModelManager().ResolveViewModel(obj&lt;/em&gt;),
dále zjistí, jestli view model podporuje rozhraní ITransientStateManager, IInitialize
a a IActivated a pokračuje takto:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Jestliže máme uložen tranzientní stav (došlo k “tombstoningu”) a view model podporuje
rozhraní ITransientStateManager, zavoláme metodu LoadState z rozhraní ITransientStateManager
(&lt;em&gt;stateManager.LoadState(LastSavedTransientState[stateKey]); &lt;/em&gt;a view model
tak dostane šanci načíst dříve uložená tranzientní data.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Když nemáme uložen tranzientní stav a view model podporuje rozhraní IInitialize, zavoláme
metodu IInitialize.Init. View model tak dostane šanci nahrát data, ať už se souboru,
z webové služby nebo jiného datového zdroje, která mají být zobrazena v aktuálním
view.&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
Poté, co view model obnoví nebo inicializuje svůj stav, je volána metoda activateAndSetDataContext,
která na view modelech podporujících rozhraní IActivated zavolá metodu Activate a
nastaví view model jako datový zdroj (“DataContext”) view.
&lt;/p&gt;
&lt;p&gt;
Nakonec pro všechny dceřiné prvky, které mohou představovat vnořená view (např. user
control), rekurzivně zavoláme opět metodu restoreTransientState. K získání dceřiných
prvků a jejich relativního indexu mezi prvky na stejné úrovni zanoření ve vizuálním
stromu je použita metoda UIHelper.GetChildren.
&lt;/p&gt;
&lt;script src="https://gist.github.com/763405.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda LoadState, restoreTransientState a další pomocné metody, o kterých jsme mluvili
v předchozích odstavcích:
&lt;/p&gt;
&lt;script src="https://gist.github.com/763410.js"&gt; &lt;/script&gt;
&lt;p&gt;
Za povšimnutí stojí ve scénáři metody restoreTransientState ještě několik dalších
věcí:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Když zjišťujeme, jestli objekt podporuje rozhraní IInitialize (metoda &lt;em&gt;getInitObjectWithSyncContext&lt;/em&gt;),
ihned do view modelu zpropagujeme synchronizační kontext (&lt;em&gt;initObject.SynchContext
= SynchronizationContext.Current&lt;/em&gt;;), aby například událost PropertyChanged mohla
být vyvolávána vždy v UI vláknu.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Pomocná metoda &lt;em&gt;selectViewModel(frameworkElement, lastViewModel, currentViewModel);&lt;/em&gt; odpovědná
za výběr view modelu zajistí, že když IViewModelResolver nenalezne pro view žádný
view model, automaticky view přiřadí view model použitý u předchozího view. Kdy to
potřebujete? Třeba když stránku rozdělíte na několik nezávislých “user controls”,
tak se můžete rozhodnout, jestli bude mít každý user control (view) svůj view model,
nebo view model vytvoříte jen pro celou stránku a “user controls” view modely automaticky
“zdědí”. To byl jen jeden příklad - úroveň zanoření view je zcela ve vaší režii. Slovo
“zdědí” je v uvozovkách, protože nejde o klasické dědení DataContextu, ale k předání
posledně použitého view modelu dojde i tehdy, když dvě view nemají společné “nadview”.&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;em&gt;Poznámka: Nejprve jsem chtěl volání metod Init a LoadState na view modelech a
následné nastavení DataContextu u view dát do jiného vlákna. Problém je v tomto případě
s dědením view modelů. Když přiřadíte view model, na kterém jste zavolali asynchronně
metodu Init, dalšímu vnořenému View, tak se může stát, že metoda Init ještě nedoběhla,
view model u prvního view nastaven není, ale u vnořeného (druhého) view již nastaven
je, což může vést k podivným a kvůli použití více vláken obtížně reprodukovatelným
chybám. Za asynchronní zpracování časově náročných scénářů zodpovídají samotné view
modely, které by měly přepisovat virtuální metodu DoInternalAsyncInit z ViewModelBase.
Metodu DoInternalAsyncInit jsem &lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;popisoval
v předchozím článku&lt;/a&gt;.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Viděli jsme, kdy hostitel volá metody Init, Activate a kdy voláním metody LoadState
obnoví tranzientní stav ve view modelech. Ještě nám zbývá projít, kdy ukládáme tranzientní
stav a kdy notifikujeme view modely voláním jejich metody Deactivate o tom, že k nim
přidružené view (stránka) není již aktivní.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Nebudeme při ukládání tranzientního stavu nijak pátrat, jestli došlo k “tombstoningu”,
ale stav view modelů do &lt;em&gt;PhoneApplicationPage.State&lt;/em&gt; uložíme vždy, když dojde
k opuštění stránky. Hlavním důsledkem tohoto rozhodnutí je, že s obsluhou metod&amp;nbsp;
Application_Launching, Application_Activated, Application_Deactivated a Application_Closing,
kterou jsem popisoval minule, se nemusíte kvůli “tombstoningu” trápit a zmíněné metody
můžete většinou zcela ignorovat.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
O opuštění stránky jsm informováni v metodě OnNavigatedFrom, kterou přepíšeme. Metoda
OnNavigatedFrom voláním metody SaveState uloží stav všech view modelů a poté metoda
handleAllDeactivated na všech modelech&amp;nbsp; podporujících rozhraní IDeactivated zavolá
metodu Deactivate.
&lt;/p&gt;
&lt;script src="https://gist.github.com/763441.js"&gt; &lt;/script&gt;
&lt;p&gt;
Popisovat kompletně logiku v metodě SaveState nemá smysl, protože tato metoda je reverzní
k metodě LoadState. Pro všechny view rekurzivně vyhledá jejich view modely a dovolí
jim uložit pod unikátním klíčem view, který je vygenerován třídou UIHelper, tranzientní
stav. Ten samý tranzientní stav view modelů, jehož obnovení v metodě LoadState jsem
popisoval výše.&amp;nbsp; &lt;script src="https://gist.github.com/763445.js"&gt; &lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
Za komentář stojí, že podmínka if&lt;em&gt; (stateManager != null &amp;amp;&amp;amp; stateManager
!= lastDataContext) &lt;/em&gt;ošetřuje, abychom neukládali trazientní stav view modelu,
který slouží jako DataContext u více View, opakovaně, ale vždy pouze jednou.
&lt;/p&gt;
&lt;p&gt;
Tranzientní stav všech view modelů je ukládán do speciálního objektu Dictionary s
názvem KnownTypesDictionary.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;var statebag = new KnownTypesDictionary();&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Připomínám, že při tombstoningu je možné uložit jen serializovatelné objekty. Představme
si nyní, že KnownTypesDictionary je potomek třídy&amp;nbsp; Dictionary&amp;lt;string, object&amp;gt;.
Do takového objektu Dictionary můžeme vložit kteroukoli instanci z třídy, která je
přímo či nepřimo potomkem třídy Object, ale při pokusu o serializaci dostaneme chybu,
protože naše potomky DataContractSerializer nezná a očekává, že v kolekci budou jen
instance třídy Object, a ne instance odvozených tříd. Pomocí atributu &lt;a href="http://msdn.microsoft.com/en-gb/library/system.runtime.serialization.knowntypeattribute.aspx"&gt;KnownType&lt;/a&gt;,
který je aplikován na KnownTypesDictionary, můžeme DataContractSerializer informovat,
které všechny třídy má v objektu Dictionary očekávat. Jednou z&amp;nbsp; možností, jak
to udělat, je předat atributu KnownType název statické metody, která seznam “známých”
tříd vrací. 
&lt;/p&gt;
&lt;p&gt;
Dnes si ukážeme jednoduchou verzi třídy&amp;nbsp; &lt;em&gt;KnownTypesDictionary&lt;/em&gt;, která
v metodě GetKnownTypes vrátí fixní seznam "známých” tříd. Příště si ukážeme, jak budou
“známé” třídy dohledány a registrovány&amp;nbsp; automaticky bez nutnosti vytvářet seznam
známých tříd vždy znovu a “natvrdo” v každé aplikaci. V dalších dílech také zjistíme,
jak právě vytvořená infrastruktura nám dovolí vytvářet WP7 aplikace příslovečným lusknutím
prstu, tedy spíš nečetným lusknutím prstů o klávesnici. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/8b4a80e9bf58_926F/wlEmoticon-smile_2.png"&gt; &lt;script src="https://gist.github.com/763469.js"&gt; &lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;
.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Předcházející články: 
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt; 
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx"&gt;Tipy
pro Windows Phone 7 aplikace II – podpora životního cyklu aplikace (včetně tombstoningu)
ve "view modelech”&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=38539832-2f1d-42cf-8549-b59697b093c4" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,38539832-2f1d-42cf-8549-b59697b093c4.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=060fbd09-0368-4733-92ad-aaecf48409a4</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=060fbd09-0368-4733-92ad-aaecf48409a4</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
 
</p>
        <p>
Již v <a href="http://Tipy pro Windows Phone 7 aplikace I">prvním dílu seriálu o vývoji
WP7 aplikací</a> jsem zmiňoval nejen to, že mobilní verze Silverlightu ve WP7 je založena
na Silverlightu 3, ale také, že mobilní Silverlight má své unikátní rysy, které v
žádné desktopové verzi Silverlightu nenalezneme. Jednou ze změn je životní cyklus
aplikace, včetně tzv. tombstoningu. Termín ”tombstoning”, kterého se i  v tomto
článku budu držet, abych nemusel zavádět nějaké směšně znějící české ekvivalenty,
má asi naznačovat, že WP7 podporují nejen tradiční spuštění a ukončení aplikace, ale
i jakýsi hybridní stav, v němž instance naší aplikace může být dočasně ukončena (“umrtvena”)
například tím, že uživatel spustí jinou aplikaci, a poté může být z hlediska uživatele
WP7 telefonu naše původní aplikace navrácena k životu,  a to dokonce ve stavu,
v jakém ji předtím uživatel zanechal. O smysluplnosti “tombstoningu” mám své pochybnosti
a raději bych ve WP7 viděl tradiční multitasking, ale vývojářův boj s chováním “zombie”
aplikací ve stavu “tombstoningu” má také něco do sebe. V tomto článku bych rád posunul
boj se “zombie-tombstonovanými” aplikacemi do dalšího levelu a nabídnul pár “cheatů”
.<img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png" /></p>
        <p>
Přechody mezi stavy WP7 aplikace nám nejlépe objasní  metody pro obsluhu životního
cyklu aplikace, které jsou po založení projektu automaticky vygenerovány v souboru
App.xaml.cs.
</p>
        <script src="https://gist.github.com/744872.js">
        </script>
        <p>
Metoda  <em>Application_Launching </em>je  provedena jednou po spuštění
aplikace. Jde o metodu, ve které můžete načíst dříve uložená data z “isolated storage”. 
Tato metoda NENÍ volána při  obnovení “tombstonované” aplikace.
</p>
        <p>
Metoda <em>Application_Closing </em>je provedena jednou při ukončení aplikace. Jde
o metodu, ve které typicky uložíte data do “isolated storage”. Jde o stejná data,
která  načtete při dalším spuštění aplikace v již popsané metodě <em>Application_Launching </em>a
můžeme tedy říci, že jde o data s delší záruční lhůtou<em>, </em>která mají význam
pro různé instance aplikace. Když stáhnete z webové služby nějaké číselníky (typy
zákazníků, kategorie objednávek) a nechcete je po startu aplikace stahovat vždy znovu,
uložíte si je a při příštím spuštění aplikace rychleji naběhne, protože nemusí stahovat
všechna data z webových služeb ihned po startu.
</p>
        <p>
Další metody se týkají již tombstoningu. Metoda <em>Application_Deactivated</em> je
volána vždy, když je vaše aplikace “tombstonována” a v této metodě byste měli uložit
všechna data, která potřebujete k tomu, abyste mohli po návratu z “tombstonovaného”
stavu aplikaci zobrazit uživateli tak, jako kdyby běžela celou dobu a k žádnému “tombstoningu”
nedošlo. Pro vývojáře ale “tombstoning” ve skutečnosti znamená, že aktuálně běžící
instance aplikace je zlikvidována! Můžeme tedy říci, že v této metodě hlavně ukládáme
data s kratší záruční lhůtou, která mají význam jen pro další instanci aplikace po
návratu z “tombstonovaného” stavu. Data, která chcete mít k dispozici i po obnovení
z “tombstoningu” můžete ukládat pod vámi zvolenými identifikátory v objektu typu IDictionary
ve vlastnosti PhoneApplicationService.Current.State. <strong>Data, která zde uložíte,
musí být serializovatelná, protože se nedrží jen v paměti telefonu, ale jsou ukládána
i do souboru.</strong></p>
        <p>
Je ale nutné si uvědomit, že když je aplikace “tombstonována”, nemáte garantováno,
že se uživatel do vaší aplikace vrátí a že budete obnoveni z “tombstonovaného” stavu.
I v této metodě je proto vhodné ukládat data, která ukládáte v metodě <em>Application_Closing </em>popsané
výše. 
</p>
        <p>
Uživatel může také spustit vaší aplikaci znovu, tedy spustit novou instanci aplikace,
aniž by se vrátil k dříve “"tombstonované” aplikaci a vy svůj stav - data, o nichž
jsem říkal, že mají kratší záruční lhůtu - dříve uložený v metodě <em>Application_Deactivated </em>nikdy
nepoužijete. Když se uživatel vrátí do vaší aplikace, což většinou nastane po stisknutí
tlačítko “Back”, kdy se v zásobníku dříve spuštěných aplikací, který je spravován
přímé operačním systémem, stane aktivním vaše aplikace, musíte obnovit dříve uložený
stav v metodě <em>Application_Activated</em>. Napsal jsem, že jde o zásobník aplikací,
ale je potřeba si uvědomit, že jde spíš o metaforu, protože aplikace a jejich stránky
nejsou nikdy fyzicky uloženy, ale při “tombstoningu” většinou bez milosti zlikvidovány,
a metoda <em>Application_Activated </em>je volána v nové instanci naší aplikace. WP7
si jen v zásobníku pamatují, jaké aplikace a v jakém pořadí byly  spuštěny a
která stránka v konkrétní aplikaci byla aktivní. 
</p>
        <p>
Dále je potřeba si osvojit tato pravidla:
</p>
        <ul>
          <li>
Metoda <em>Application_Activated </em><strong>NENÍ</strong> volána po spuštění nové
(“netombstonované”) instance aplikace. Po spuštění nové (“netombstonované”) instance
aplikace je volána pouze metoda <em>Application_Launching.<br /></em></li>
          <li>
Metoda <em>Application_Deactivated</em><strong>NENÍ</strong> volána při  úplném
ukončení aplikace. Při  úplném ukončení aplikace je volána pouze metoda <em><em>Application_Closing</em>.</em></li>
        </ul>
        <p>
Zjednodušeně bychom mohli odpovědnosti metod v souboru App.xaml.cs popsat tímto fragmentem
kódu:
</p>
        <script src="https://gist.github.com/744916.js">
        </script>
        <p>
Měli bychom ale vědět, že k tombstoningu může dojít kdykoli a podle mých testů na
emulátoru i reálném zařízení může být aplikace “tombstonována”, i když se zrovna obnovuje
z předchozího “tombstonovaného” stavu a je v metodě “<em>Application_Activated“.  </em>Autoři
WP7 se s “tombstoningem” moc nepatlají a bez skrupulí po určité době zlikvidují vlákna
aplikace, což poznáte podle výjimky <em>ThreadAbortException.</em></p>
        <p>
Také se mi nelíbí, že bych měl v tomto jediném souboru ukládat a obnovovat data pro
všechny stránky (“formuláře”) aplikace. Rozhodl jsem se, že na obsluhu těchto metod
rezignuju a místo životní cyklu aplikace se budu zajímat jen o životní cyklus view
modelu (presentation modelu, chcete-li) u každé stránky ve WP7 aplikaci.
</p>
        <p>
Dnes si ukážeme bázovou třídu pro view modely a další podpůrné třídy se službami,
která nás svou spoluprací zbaví nutnosti při psaní každé stránky myslet na to, že
autoři WP7 aplikací se vyžívají v recidivě nekrofilního chování u WP7 aplikací. Drahý
bratr Sigmund Freud by se po prohlídce stavového automatu “tombstonované“ aplikace
od architektů WP7 na své pohovce jistě tetelil radostí nad předaným šokujícím materiálem. <img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png" /></p>
        <p>
Nejdříve si ale navrhneme minimální množinu vlastností, kterou by měl každý view model
splňovat, abychom se již nemuseli životním cyklem WP7 aplikace příliš zabývat při
návrhu každé stránky.
</p>
        <ol>
          <li>
Musíme být schopni nahrát data při vytvoření nového view modulu. Také bychom měli
zajistit, že když dojde k “tombstoningu” aplikace ještě před získáním všech dat, nezůstane
view model v nějakém nekonzistentním stavu s třetinou nahraných dat, ale po obnovení
z “tombstoningu” dostane šanci nahrát data znovu. 
<br /><br /><script src="https://gist.github.com/744974.js"></script></li>
          <li>
Budeme schopni při “tombstoningu” automaticky perzistovat dočasný stav každého view
modelu. Od této chvíle začneme říkat dočasnému stavu stav tranzientní.<em> V tomto
článku se zabývám jen tranzientním stavem aplikace, o perzistování “trvanlivějších”
dat do “isolated storage” se pobavíme v některém z dalších článků.</em><br /></li>
          <li>
Po obnovení aplikace z “tombstonovaného” stavu každý view model automaticky nahraje
svůj tranzientní stav.<br />
Pro uložení a nahrání tranzientního stavu nadefinujeme rozhrani ITransientStateManager.<br /><br /><script src="https://gist.github.com/744980.js"></script></li>
          <li>
Měli bychom dát šanci view modelům zareagovat na to, že stránka, ke které jsou přidruženy,
se stala aktivní stránkou, i na to, že k nim přidružená stránka aktivní už není, ať
už proto, že došlo k “tombstoningu” nebo uživatel přešel na jinou stránku v aplikaci.<br />
Pro tyto účely máme rozhraní IActivated a IDeactivated.<br /><br /><script src="https://gist.github.com/744991.js"></script></li>
          <li>
Budeme mít sice bázovou třídu pro view modely, ale její použití si nebudeme vynucovat.
View model může být v aplikaci kterákoli třída. I když tato třída nebude potomkem
bázové třídy pro view modely, bude moci volitelně využít většinu služeb, které jsou
popsány v přechozích bodech.<br /><br /></li>
          <li>
Jedná se o view modely, měli bychom tedy na úrovní bázové třídy podporovat rozhraní
INotifyPropertyChanged, které nám dovoluje notifikovat o změně hodnoty ve vlastnostech
view modelu. Rozhraní INotifyPropertyChanged je ve WPF i v Silverlight aplikacích
všudypřítomné, proto si navrhneme další bázovou třídu PropertyChangedBase, která nám
kromě implementace rozhraní INotifyPropertyChanged přinese další užitečné služby.<br /><script src="https://gist.github.com/745001.js"></script></li>
        </ol>
        <p>
 
</p>
        <p>
Jaké další užitečné služby má třída PropertyChangedBase?
</p>
        <p>
Nemusíme vyvolávat událost PropertyChanged zadáním jen zadáním názvu vlastnosti (<em>RaisePropertyChanged(“UserName”)</em>),
což může vést k chybě za běhu aplikace, když uděláme překlep v názvu vlastnosti (<em>(RaisePropertyChanged(“UseName”)</em>),
ale můžeme předat název vlastnosti ve formě lambda výrazu, jehož syntaxe je zkontrolována
již kompilátorem. K tomu nám slouží metoda <em>RaisePropertyChangedEvent<treturn>
(Expression<func><treturn>
&gt; propertyDefinition)
</treturn></func></treturn></em>. Potomci třídy PropertyChangedBase mohou o změně hodnoty vlastnosti
informovat takto:
</p>
        <script src="https://gist.github.com/745018.js">
        </script>
        <p>
U potomků třídy PropertyChangedBase, kterými budou i naše view modely, si můžeme také
zavoláním metody <em>RaiseAllPropertiesChanged</em> vynutit vyvolání události o změně
hodnoty pro každou vlastnost. Další metodě s názvem <em>RaisePropertiesChanged(params
string[] properties) </em>můžeme předat názvy vlastností, pro které má být vyvolána
metoda PropertyChanged.
</p>
        <p>
A teď si  již můžeme vytvořit slibovanou třídu ViewModelBase, která je potomkem
třídy PropertyChangedBase a podporuje všechna rozhraní zmíněná dříve.
</p>
        <script src="https://gist.github.com/745046.js">
        </script>
        <p>
 
</p>
        <p>
V konstruktoru třída ViewModelBase přijímá titulek zobrazované stránky, který je uložen
do vlastnosti PageTitle.
</p>
        <script src="https://gist.github.com/745079.js">
        </script>
        <p>
Metoda Init z rozhraní Initialize by měla být volána vždy, když je view model vytvořen,
nebo když je po obnovení aplikace z “tombstonovaného” stavu zřejmé, že view model
nenahrál všechna data, což se zjistí voláním virtuální metody <em>IsAllInitDataLoaded</em>,
která v této abstraktní třídě vždy  vrací true a čeká na to, až odvozené konkrétní
view modely dosadí svou logiku, kdy je považován view model za nahraný. Metoda Init
by měla být taky volána, když odvozený view model obnovená tranzientní data považuje
za špatná / zastaralá a nemůže je používat, což nám dá najevo nastavením vlastnosti <em>IsInvalidModel</em> na
true. K rychlému zjištění, jestli  je možné view model dále používat slouží derivovaná
vlastnost <em>CanUseModel</em>, která spojuje logiku obsaženou ve vlastnosti <em>IsInvalidModel</em> a
metodě <em>IsAllInitDataLoaded.</em></p>
        <script src="https://gist.github.com/745094.js">
        </script>
        <p>
 
</p>
        <p>
Metoda <em>Initialize.Init</em></p>
        <script src="https://gist.github.com/745104.js">
        </script>
        <p>
V metodě <em>Init</em> nejdříve nastavíme vlastnost <em>IsInvalidModel</em> na true,
protože naše metoda <em>Init</em> probíhá a kdyby došlo k “tombstoningu”, nemáme všechna
data a je potřeba volat metodu <em>Init</em> znovu. Poté jen načteme titulek aplikace
do vlastnosti <em>AppTitle</em>,  inicializujeme vlastnost <em>SuppressValidating</em>,
která slouží k dočasnému potlačení ověřování platnosti data zadaných uživatelem ve
view modelu, na hodnotu false. <em>O vlastnosti SuppressValidating budeme více mluvit
v dalším článku včetně vysvětlení významu metody ValidateData a vlastnosti HasValidData. 
<br /></em></p>
        <p>
Dále <em>ViewModelBase</em> nastavením vlastnosti <em>IsInvalidModel</em> na false
sděluje, že jeho inicializace proběhla, všechna data v modelu považuje za platná a
dá šanci odvozeným třídám, aby inicializovaly svá data voláním chráněné virtuální
metody <em>DoInternalInit</em>, která má ve <em>ViewModelBase</em> prázdnou implementaci
a do které odvozené třídy dají svou specifickou logiku pro načtení dat. Vlastnost <em>IsInvalidModel</em> mohou
samozřejmě odvozené třídy nastavit v metodě <em>DoInternalInit</em> opět na true,
ale my ve vlastnosti <em>IsInvalidModel</em> hodnotu true nenecháváme, protože si
přepsání metody <em>DoInternalInit</em> v odvozených třídách nevynucujeme a v bázové
třídě ViewModelBase nemůžeme vědět, kdy odvozené třídy považují svá data za neplatná.
</p>
        <p>
V metodě <strong>Init </strong>nakonec také voláním metody další chráněné virtuální
metody s názvem <em>DoInternalAsyncInit</em> v <strong>samostatném vlákně </strong>šanci
odvozeným třídám <strong>asynchronně </strong>inicializovat svá data. Metodu <em>DoInternalAsyncInit</em> by
měly odvozené třídy používat k časově náročné inicializaci, kterou není vhodné vhodné
dávat do synchronně  volané metody DoInternalInit a blokovat tak hlavní thread
aplikace.
</p>
        <p>
Mohlo by vás také zaujmout, že v sekci catch má speciální zacházení výjimka <em>ThreadAbortException
– </em>tato výjimka není propagována výše, protože ji vyvolá samotné běhové prostředí
Silverlightu při násilném “tombstoningu”, jak jsem poznamenal na začátku tohoto článku.
</p>
        <p>
 
</p>
        <p>
Rozhraní <em>IActivated</em> s metodou <strong>Activate </strong>a<strong></strong>rozhraní<strong></strong><em>IDeactivated </em>s
metodou <strong>Deactivate</strong> ve <em>ViewModelBase</em> mají jen prázdnou implementaci
a čekají na to, jakou logiku do nich vloží odvozené třídy. Mimochodem  – na tomto
místě bychom měli poprvé vytušit, že budeme potřebovat “hostitele” našich view modelů,
který bude vědět, kdy volat metody <em>Activate</em>, <em>Deactivate</em>, <em>Init</em> a
další.<br /></p>
        <p>
Třída ViewModelBase explicitně implementuje rozhraní <em>ITransientStateManager</em>,
které jsme si zavedli pro podporu automatického ukládání a nahrávání tranzientního
stavu. Metody <em>LoadState</em> a <em>SaveState</em> ale po svém vyvolání jen předají
řízení chráněným virtuálním metodám <em>DoInternalLoadTransientState</em> a <em>DoInternalSaveTransientState, </em>aby
dali šanci i odvozeným třídám změnit způsob uložení a nahrání tranzientního stavu,
i když odvozené třídy jsou většinou spokojeni s tím, že to za ně zvládne předek ViewModelBase.
</p>
        <p>
 
</p>
        <script src="https://gist.github.com/745208.js">
        </script>
        <p>
Třída ViewModelBase ve svém statickém konstruktoru dosazuje výchozí objekt podporující
rozhraní <em>ITransientStateHelper</em>, které je klíčové pro uložení a obnovení tranzientního
stavu view modelů a na které delegují i metody <em>DoInternalLoadTransientState</em> 
a <em>DoInternalSaveTransientState</em> v předchozím výpisu.
</p>
        <p>
Všimněte si, že metoda <em>DoInternalLoadTransientState </em>po obnovení tranzientního
stavu zkontroluje, jestli se dá view model používat, a pokud ne, zavolá i v této fázi
metodu Init.
</p>
        <p>
          <em>if (!CanUseModel)<br />
{</em>
        </p>
        <p>
          <em>  Init();<br />
}</em>
        </p>
        <p>
A nyní se podíváme na mocné rozhraní <em>ITransientStateHelper</em></p>
        <strong>
        </strong>
        <script src="https://gist.github.com/745212.js">
        </script>
        <p>
Je asi zřejmé, že metoda <em>GetTransientState</em> vrátí v objektu Dictionary tranzientní
stav objektu, který jí byl předán v argumentu obj. Metoda <em>RestoreTransientState</em> naopak
obnoví tranzientní stav objektu v argumentu obj hodnotami v argumentu savedState.
</p>
        <p>
Metoda <em>IsTransientStateEnabledForObject</em> zjistí, jestli je možné z předaného
objektu získat tranzientní stav. Jak uvidíme, odvozené view modely mohou odmítnout
uložení tranzientního stavu a kdekoli v aplikaci  můžeme jejich rozhodnutí jednoduše
zjistit předáním instance view modelu této metodě.
</p>
        <p>
Zde je jedna z možných realizací rozhraní IStateTransientStateHelper, kterou používá
i naše třída ViewModelBase.
</p>
        <script src="https://gist.github.com/745247.js">
        </script>
        <p>
 
</p>
        <p>
Odpovědnosti metod <em>GetTransientState</em> a <em>RestoreTransientState</em> jsem
již popsal, nyní jen zmíním pár specialitek v kódu třídy TransientStateHelper.
</p>
        <p>
Metoda GetTransientState zjistí, jestli předaný objekt  má tranzientní stav tak,
že zavolá metodu <strong>IsTransientStateEnabledForObject(obj)<em>.</em></strong></p>
        <p>
Metoda IsTransientStateEnabledForObject kontroluje, jestli třída, ze které objekt
pochází, nezakázala vydání tranzientního stavu tím, že je na ní aplikován atribut
[NonTransientState].
</p>
        <p>
Atribut NonTransientState
</p>
        <script src="https://gist.github.com/745279.js">
        </script>
        <p>
Atribut NonTransientState může být aplikován nejen na celou třídu, ale i na jednotlivé
vlastnosti objektu, které nemají být součástí tranzientního stavu.  <strong>Metoda
GetTransientState neukládá celé view modely, ale s využitím reflexe jen hodnoty jejich
vlastností. Atribut NonTransientState dovoluje vyřadit vlastnosti, které v tranzientním
stavu view modelu nemají co dělat.</strong> To ale není vše – přímo metoda GetTransientState
dle jmenné konvence vyřadí všechny vlastnosti, jejichž suffix je v poli IGNORE_METHOD_SUFFIX_LIST 
</p>
        <p>
          <em>public static readonly IEnumerable<string>
IGNORE_METHOD_SUFFIX_LIST = new[] { "Command", "Action", "Helper", "Service", "SynchContext"};
</string></em>
        </p>
        <p>
Do tranzientního stavu se tak nedostanou ve view modelech se často nacházející, ale
s tranzientním stavem view modelu nic nemající a navíc většinou neserializovatelné
objekty jako jsou objekty ICommand (vlastnost Select<strong>Command</strong>, Save<strong>Command</strong>),
delegáti  TextboxTextChanged<strong>Action</strong>, služby (ILogger<strong>Service</strong>)
a další.
</p>
        <p>
Metoda <em>RestoreTransientState</em> obnoví tranzientní stav objektu. Za zmínku stojí,
že když je předaný objekt potomkem PropertyNotificationBase, tak nastavením vlastnosti
notificationBase.SuppressPropertyChangedNotification na true potlačíme dočasně vyvolání
události OnPropertyChanged, protože je vhodné, abychom událost nevyvolávali, když
view model neobsahuje všechna data a nevíme, kdo všechno na událost reaguje a jaká
další, nyní ve view modelu se nenacházející data, by chtěl načíst. Jak jsem ale psal
v požadavcích na začátku článku, view model nemusí podporovat žádná rozhraní, nemusí
být potomkem ViewModelBase ani PropertyNotificationBase, a proto si ani dědění z PropertyNotificationBase
v této metodě nevynucujeme. Poté, co metoda <em>RestoreTransientState </em>obnoví
hodnoty všech vlastností, má TransientStateHelper povinnost notifikovat okolí o změně
hodnot všech vlastností view modelu. Jestliže je objekt s obnoveným tranzientním stavem
potomkem PropertyNotificationBase, zavoláme metodu RaisePropertiesChanged(propertyNames.ToArray()),
jinak se metoda <em>RestoreTransientState</em> pokusí dohledat opět za pomoci reflexe
na objektu metodu nazvanou RaisePropertyChangedEvent, která přijímá název vlastnosti
a kterou použije pro hromadnou distribuci událostí OnPropertyChanged.
</p>
        <p>
Ovládací prvky obsažené (nejen) v control toolkitu jsou  přecitlivělé na pořadí
vyvolávání události, a proto jsou vlastnosti seřazeny nyní tak, aby vlastnosti začínající
slovem <em>Selected</em><strong></strong>vyvolávaly událost OnPropertyChanged jako
poslední. Máte-li ve view modelu kolekci nazvanou Orders (všechny objednávky) a SelectedOrder
(vybraná objednávka z této kolekce), je zaručeno, že <strong>událost OnPropertyChanged
pro vlastnost SelectedOrder bude vyvolána až po události OnPropertyChanged pro vlastnost
Orders.</strong></p>
        <p>
          <em>Prefixy vlastností, které mají vyvolávat události jako poslední, jsou v proměnné
LAST_SET_VALUE_METHOD_PREFIX. Tyto vlastnosti jsou označeny příznakem LastInit z enumerace
PropertyType.</em>
        </p>
        <p>
          <em>
          </em>
        </p>
        <p>
          <em>public static readonly IEnumerable<string>
LAST_SET_VALUE_METHOD_PREFIX = new[] { "Selected" };
</string></em>
        </p>
        <p>
To by pro dnešek k třídě ViewModelBase a jejím pomocníkům stačilo:
</p>
        <p>
Příště se podíváme hlavně na “hostitele” view modelů, který by měl být schopen:
</p>
        <ul>
          <li>
Volat na view modelech ve “správnou dobu” metody Init, LoadState, SaveState, Activate,
Deactivate. 
<br /></li>
          <li>
Připojit view modely k view (stránce).<br /></li>
          <li>
Náš hostitel bude podporovat i více view modelů na jedné stránce, včetně “dědění”
a sdílení použitých view modelů mezi různými view na stránce.</li>
        </ul>
        <p>
A také si příště vysvětlíme, proč při získání tranzientního stavu ve ViewModelbase
místo objektu Dictionary používáme vlastní třídu KnownTypesDictionary. Jak možná tušíte,
i název “KnownTypes” odkazuje k tomu, že mají-li být hodnoty uložené v tranzientním
stavu serializovatelné, tak <em>DataContractSerializer,</em> používaný infrastrukturou
WP7 k serializaci tranzientního stavu, musíme přesvědčit, že v objektu Dictionary
jsou jen objekty z jemu “známých” tříd.
</p>
        <p>
Předcházející články:
</p>
        <p>
          <a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx">Tipy
pro Windows Phone 7 aplikace I</a>
        </p>
        <img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=060fbd09-0368-4733-92ad-aaecf48409a4" />
      </body>
      <title>Tipy pro Windows Phone 7 aplikace II &amp;ndash; podpora životn&amp;iacute;ho cyklu aplikace (včetně tombstoningu) ve &amp;quot;view modelech&amp;rdquo;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+II+Ndash+Podpora+%c5%bdivotniacuteho+Cyklu+Aplikace+V%c4%8detn%c4%9b+Tombstoningu+Ve+Quotview+Modelechrdquo.aspx</link>
      <pubDate>Fri, 17 Dec 2010 18:25:14 GMT</pubDate>
      <description>&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Již v &lt;a href="http://Tipy pro Windows Phone 7 aplikace I"&gt;prvním dílu seriálu o vývoji
WP7 aplikací&lt;/a&gt; jsem zmiňoval nejen to, že mobilní verze Silverlightu ve WP7 je založena
na Silverlightu 3, ale také, že mobilní Silverlight má své unikátní rysy, které v
žádné desktopové verzi Silverlightu nenalezneme. Jednou ze změn je životní cyklus
aplikace, včetně tzv. tombstoningu. Termín ”tombstoning”, kterého se i&amp;nbsp; v tomto
článku budu držet, abych nemusel zavádět nějaké směšně znějící české ekvivalenty,
má asi naznačovat, že WP7 podporují nejen tradiční spuštění a ukončení aplikace, ale
i jakýsi hybridní stav, v němž instance naší aplikace může být dočasně ukončena (“umrtvena”)
například tím, že uživatel spustí jinou aplikaci, a poté může být z hlediska uživatele
WP7 telefonu naše původní aplikace navrácena k životu,&amp;nbsp; a to dokonce ve stavu,
v jakém ji předtím uživatel zanechal. O smysluplnosti “tombstoningu” mám své pochybnosti
a raději bych ve WP7 viděl tradiční multitasking, ale vývojářův boj s chováním “zombie”
aplikací ve stavu “tombstoningu” má také něco do sebe. V tomto článku bych rád posunul
boj se “zombie-tombstonovanými” aplikacemi do dalšího levelu a nabídnul pár “cheatů”
.&lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Přechody mezi stavy WP7 aplikace nám nejlépe objasní&amp;nbsp; metody pro obsluhu životního
cyklu aplikace, které jsou po založení projektu automaticky vygenerovány v souboru
App.xaml.cs.
&lt;/p&gt;
&lt;script src="https://gist.github.com/744872.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda&amp;nbsp; &lt;em&gt;Application_Launching &lt;/em&gt;je&amp;nbsp; provedena jednou po spuštění
aplikace. Jde o metodu, ve které můžete načíst dříve uložená data z “isolated storage”.&amp;nbsp;
Tato metoda NENÍ volána při&amp;nbsp; obnovení “tombstonované” aplikace.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;Application_Closing &lt;/em&gt;je provedena jednou při ukončení aplikace. Jde
o metodu, ve které typicky uložíte data do “isolated storage”. Jde o stejná data,
která&amp;nbsp; načtete při dalším spuštění aplikace v již popsané metodě &lt;em&gt;Application_Launching &lt;/em&gt;a
můžeme tedy říci, že jde o data s delší záruční lhůtou&lt;em&gt;, &lt;/em&gt;která mají význam
pro různé instance aplikace. Když stáhnete z webové služby nějaké číselníky (typy
zákazníků, kategorie objednávek) a nechcete je po startu aplikace stahovat vždy znovu,
uložíte si je a při příštím spuštění aplikace rychleji naběhne, protože nemusí stahovat
všechna data z webových služeb ihned po startu.
&lt;/p&gt;
&lt;p&gt;
Další metody se týkají již tombstoningu. Metoda &lt;em&gt;Application_Deactivated&lt;/em&gt; je
volána vždy, když je vaše aplikace “tombstonována” a v této metodě byste měli uložit
všechna data, která potřebujete k tomu, abyste mohli po návratu z “tombstonovaného”
stavu aplikaci zobrazit uživateli tak, jako kdyby běžela celou dobu a k žádnému “tombstoningu”
nedošlo. Pro vývojáře ale “tombstoning” ve skutečnosti znamená, že aktuálně běžící
instance aplikace je zlikvidována! Můžeme tedy říci, že v této metodě hlavně ukládáme
data s kratší záruční lhůtou, která mají význam jen pro další instanci aplikace po
návratu z “tombstonovaného” stavu. Data, která chcete mít k dispozici i po obnovení
z “tombstoningu” můžete ukládat pod vámi zvolenými identifikátory v objektu typu IDictionary
ve vlastnosti PhoneApplicationService.Current.State. &lt;strong&gt;Data, která zde uložíte,
musí být serializovatelná, protože se nedrží jen v paměti telefonu, ale jsou ukládána
i do souboru.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Je ale nutné si uvědomit, že když je aplikace “tombstonována”, nemáte garantováno,
že se uživatel do vaší aplikace vrátí a že budete obnoveni z “tombstonovaného” stavu.
I v této metodě je proto vhodné ukládat data, která ukládáte v metodě &lt;em&gt;Application_Closing &lt;/em&gt;popsané
výše. 
&lt;/p&gt;
&lt;p&gt;
Uživatel může také spustit vaší aplikaci znovu, tedy spustit novou instanci aplikace,
aniž by se vrátil k dříve “"tombstonované” aplikaci a vy svůj stav - data, o nichž
jsem říkal, že mají kratší záruční lhůtu - dříve uložený v metodě &lt;em&gt;Application_Deactivated &lt;/em&gt;nikdy
nepoužijete. Když se uživatel vrátí do vaší aplikace, což většinou nastane po stisknutí
tlačítko “Back”, kdy se v zásobníku dříve spuštěných aplikací, který je spravován
přímé operačním systémem, stane aktivním vaše aplikace, musíte obnovit dříve uložený
stav v metodě &lt;em&gt;Application_Activated&lt;/em&gt;. Napsal jsem, že jde o zásobník aplikací,
ale je potřeba si uvědomit, že jde spíš o metaforu, protože aplikace a jejich stránky
nejsou nikdy fyzicky uloženy, ale při “tombstoningu” většinou bez milosti zlikvidovány,
a metoda &lt;em&gt;Application_Activated &lt;/em&gt;je volána v nové instanci naší aplikace. WP7
si jen v zásobníku pamatují, jaké aplikace a v jakém pořadí byly&amp;nbsp; spuštěny a
která stránka v konkrétní aplikaci byla aktivní. 
&lt;/p&gt;
&lt;p&gt;
Dále je potřeba si osvojit tato pravidla:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Metoda &lt;em&gt;Application_Activated &lt;/em&gt;&lt;strong&gt;NENÍ&lt;/strong&gt; volána po spuštění nové
(“netombstonované”) instance aplikace. Po spuštění nové (“netombstonované”) instance
aplikace je volána pouze metoda &lt;em&gt;Application_Launching.&lt;br&gt;
&lt;/em&gt; 
&lt;li&gt;
Metoda &lt;em&gt;Application_Deactivated&lt;/em&gt; &lt;strong&gt;NENÍ&lt;/strong&gt; volána při&amp;nbsp; úplném
ukončení aplikace. Při&amp;nbsp; úplném ukončení aplikace je volána pouze metoda &lt;em&gt;&lt;em&gt;Application_Closing&lt;/em&gt;.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Zjednodušeně bychom mohli odpovědnosti metod v souboru App.xaml.cs popsat tímto fragmentem
kódu:
&lt;/p&gt;
&lt;script src="https://gist.github.com/744916.js"&gt; &lt;/script&gt;
&lt;p&gt;
Měli bychom ale vědět, že k tombstoningu může dojít kdykoli a podle mých testů na
emulátoru i reálném zařízení může být aplikace “tombstonována”, i když se zrovna obnovuje
z předchozího “tombstonovaného” stavu a je v metodě “&lt;em&gt;Application_Activated“.&amp;nbsp; &lt;/em&gt;Autoři
WP7 se s “tombstoningem” moc nepatlají a bez skrupulí po určité době zlikvidují vlákna
aplikace, což poznáte podle výjimky &lt;em&gt;ThreadAbortException.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Také se mi nelíbí, že bych měl v tomto jediném souboru ukládat a obnovovat data pro
všechny stránky (“formuláře”) aplikace. Rozhodl jsem se, že na obsluhu těchto metod
rezignuju a místo životní cyklu aplikace se budu zajímat jen o životní cyklus view
modelu (presentation modelu, chcete-li) u každé stránky ve WP7 aplikaci.
&lt;/p&gt;
&lt;p&gt;
Dnes si ukážeme bázovou třídu pro view modely a další podpůrné třídy se službami,
která nás svou spoluprací zbaví nutnosti při psaní každé stránky myslet na to, že
autoři WP7 aplikací se vyžívají v recidivě nekrofilního chování u WP7 aplikací. Drahý
bratr Sigmund Freud by se po prohlídce stavového automatu “tombstonované“ aplikace
od architektů WP7 na své pohovce jistě tetelil radostí nad předaným šokujícím materiálem. &lt;img style="border-bottom-style: none; border-right-style: none; border-top-style: none; border-left-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.renestein.net/content/binary/Windows-Live-Writer/Tipy-pro-Windows-Phone-7-aplikace-II_A042/wlEmoticon-smile_2.png"&gt;
&lt;/p&gt;
&lt;p&gt;
Nejdříve si ale navrhneme minimální množinu vlastností, kterou by měl každý view model
splňovat, abychom se již nemuseli životním cyklem WP7 aplikace příliš zabývat při
návrhu každé stránky.
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
Musíme být schopni nahrát data při vytvoření nového view modulu. Také bychom měli
zajistit, že když dojde k “tombstoningu” aplikace ještě před získáním všech dat, nezůstane
view model v nějakém nekonzistentním stavu s třetinou nahraných dat, ale po obnovení
z “tombstoningu” dostane šanci nahrát data znovu. 
&lt;br&gt;
&lt;br&gt;
&lt;script src="https://gist.github.com/744974.js"&gt; &lt;/script&gt;
&lt;li&gt;
Budeme schopni při “tombstoningu” automaticky perzistovat dočasný stav každého view
modelu. Od této chvíle začneme říkat dočasnému stavu stav tranzientní.&lt;em&gt; V tomto
článku se zabývám jen tranzientním stavem aplikace, o perzistování “trvanlivějších”
dat do “isolated storage” se pobavíme v některém z dalších článků.&lt;/em&gt;
&lt;br&gt;
&lt;li&gt;
Po obnovení aplikace z “tombstonovaného” stavu každý view model automaticky nahraje
svůj tranzientní stav.&lt;br&gt;
Pro uložení a nahrání tranzientního stavu nadefinujeme rozhrani ITransientStateManager.&lt;br&gt;
&lt;br&gt;
&lt;script src="https://gist.github.com/744980.js"&gt; &lt;/script&gt;
&lt;li&gt;
Měli bychom dát šanci view modelům zareagovat na to, že stránka, ke které jsou přidruženy,
se stala aktivní stránkou, i na to, že k nim přidružená stránka aktivní už není, ať
už proto, že došlo k “tombstoningu” nebo uživatel přešel na jinou stránku v aplikaci.&lt;br&gt;
Pro tyto účely máme rozhraní IActivated a IDeactivated.&lt;br&gt;
&lt;br&gt;
&lt;script src="https://gist.github.com/744991.js"&gt; &lt;/script&gt;
&lt;li&gt;
Budeme mít sice bázovou třídu pro view modely, ale její použití si nebudeme vynucovat.
View model může být v aplikaci kterákoli třída. I když tato třída nebude potomkem
bázové třídy pro view modely, bude moci volitelně využít většinu služeb, které jsou
popsány v přechozích bodech.&lt;br&gt;
&lt;br&gt;
&lt;li&gt;
Jedná se o view modely, měli bychom tedy na úrovní bázové třídy podporovat rozhraní
INotifyPropertyChanged, které nám dovoluje notifikovat o změně hodnoty ve vlastnostech
view modelu. Rozhraní INotifyPropertyChanged je ve WPF i v Silverlight aplikacích
všudypřítomné, proto si navrhneme další bázovou třídu PropertyChangedBase, která nám
kromě implementace rozhraní INotifyPropertyChanged přinese další užitečné služby.&lt;br&gt;
&lt;script src="https://gist.github.com/745001.js"&gt; &lt;/script&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Jaké další užitečné služby má třída PropertyChangedBase?
&lt;/p&gt;
&lt;p&gt;
Nemusíme vyvolávat událost PropertyChanged zadáním jen zadáním názvu vlastnosti (&lt;em&gt;RaisePropertyChanged(“UserName”)&lt;/em&gt;),
což může vést k chybě za běhu aplikace, když uděláme překlep v názvu vlastnosti (&lt;em&gt;(RaisePropertyChanged(“UseName”)&lt;/em&gt;),
ale můžeme předat název vlastnosti ve formě lambda výrazu, jehož syntaxe je zkontrolována
již kompilátorem. K tomu nám slouží metoda &lt;em&gt;RaisePropertyChangedEvent&lt;treturn&gt;
(Expression&lt;func&gt;
&lt;treturn&gt;
&amp;gt; propertyDefinition)
&lt;/em&gt;. Potomci třídy PropertyChangedBase mohou o změně hodnoty vlastnosti informovat
takto:
&lt;/p&gt;
&lt;script src="https://gist.github.com/745018.js"&gt; &lt;/script&gt;
&lt;p&gt;
U potomků třídy PropertyChangedBase, kterými budou i naše view modely, si můžeme také
zavoláním metody &lt;em&gt;RaiseAllPropertiesChanged&lt;/em&gt; vynutit vyvolání události o změně
hodnoty pro každou vlastnost. Další metodě s názvem &lt;em&gt;RaisePropertiesChanged(params
string[] properties) &lt;/em&gt;můžeme předat názvy vlastností, pro které má být vyvolána
metoda PropertyChanged.
&lt;/p&gt;
&lt;p&gt;
A teď si&amp;nbsp; již můžeme vytvořit slibovanou třídu ViewModelBase, která je potomkem
třídy PropertyChangedBase a podporuje všechna rozhraní zmíněná dříve.
&lt;/p&gt;
&lt;script src="https://gist.github.com/745046.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
V konstruktoru třída ViewModelBase přijímá titulek zobrazované stránky, který je uložen
do vlastnosti PageTitle.
&lt;/p&gt;
&lt;script src="https://gist.github.com/745079.js"&gt; &lt;/script&gt;
&lt;p&gt;
Metoda Init z rozhraní Initialize by měla být volána vždy, když je view model vytvořen,
nebo když je po obnovení aplikace z “tombstonovaného” stavu zřejmé, že view model
nenahrál všechna data, což se zjistí voláním virtuální metody &lt;em&gt;IsAllInitDataLoaded&lt;/em&gt;,
která v této abstraktní třídě vždy&amp;nbsp; vrací true a čeká na to, až odvozené konkrétní
view modely dosadí svou logiku, kdy je považován view model za nahraný. Metoda Init
by měla být taky volána, když odvozený view model obnovená tranzientní data považuje
za špatná / zastaralá a nemůže je používat, což nám dá najevo nastavením vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; na
true. K rychlému zjištění, jestli&amp;nbsp; je možné view model dále používat slouží derivovaná
vlastnost &lt;em&gt;CanUseModel&lt;/em&gt;, která spojuje logiku obsaženou ve vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; a
metodě &lt;em&gt;IsAllInitDataLoaded.&lt;/em&gt;
&lt;/p&gt;
&lt;script src="https://gist.github.com/745094.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;Initialize.Init&lt;/em&gt; 
&lt;/p&gt;
&lt;script src="https://gist.github.com/745104.js"&gt; &lt;/script&gt;
&lt;p&gt;
V metodě &lt;em&gt;Init&lt;/em&gt; nejdříve nastavíme vlastnost &lt;em&gt;IsInvalidModel&lt;/em&gt; na true,
protože naše metoda &lt;em&gt;Init&lt;/em&gt; probíhá a kdyby došlo k “tombstoningu”, nemáme všechna
data a je potřeba volat metodu &lt;em&gt;Init&lt;/em&gt; znovu. Poté jen načteme titulek aplikace
do vlastnosti &lt;em&gt;AppTitle&lt;/em&gt;,&amp;nbsp; inicializujeme vlastnost &lt;em&gt;SuppressValidating&lt;/em&gt;,
která slouží k dočasnému potlačení ověřování platnosti data zadaných uživatelem ve
view modelu, na hodnotu false. &lt;em&gt;O vlastnosti SuppressValidating budeme více mluvit
v dalším článku včetně vysvětlení významu metody ValidateData a vlastnosti HasValidData. 
&lt;br&gt;
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Dále &lt;em&gt;ViewModelBase&lt;/em&gt; nastavením vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; na false
sděluje, že jeho inicializace proběhla, všechna data v modelu považuje za platná a
dá šanci odvozeným třídám, aby inicializovaly svá data voláním chráněné virtuální
metody &lt;em&gt;DoInternalInit&lt;/em&gt;, která má ve &lt;em&gt;ViewModelBase&lt;/em&gt; prázdnou implementaci
a do které odvozené třídy dají svou specifickou logiku pro načtení dat. Vlastnost &lt;em&gt;IsInvalidModel&lt;/em&gt; mohou
samozřejmě odvozené třídy nastavit v metodě &lt;em&gt;DoInternalInit&lt;/em&gt; opět na true,
ale my ve vlastnosti &lt;em&gt;IsInvalidModel&lt;/em&gt; hodnotu true nenecháváme, protože si
přepsání metody &lt;em&gt;DoInternalInit&lt;/em&gt; v odvozených třídách nevynucujeme a v bázové
třídě ViewModelBase nemůžeme vědět, kdy odvozené třídy považují svá data za neplatná.
&lt;/p&gt;
&lt;p&gt;
V metodě &lt;strong&gt;Init &lt;/strong&gt;nakonec také voláním metody další chráněné virtuální
metody s názvem &lt;em&gt;DoInternalAsyncInit&lt;/em&gt; v &lt;strong&gt;samostatném vlákně &lt;/strong&gt;šanci
odvozeným třídám &lt;strong&gt;asynchronně &lt;/strong&gt;inicializovat svá data. Metodu &lt;em&gt;DoInternalAsyncInit&lt;/em&gt; by
měly odvozené třídy používat k časově náročné inicializaci, kterou není vhodné vhodné
dávat do synchronně&amp;nbsp; volané metody DoInternalInit a blokovat tak hlavní thread
aplikace.
&lt;/p&gt;
&lt;p&gt;
Mohlo by vás také zaujmout, že v sekci catch má speciální zacházení výjimka &lt;em&gt;ThreadAbortException
– &lt;/em&gt;tato výjimka není propagována výše, protože ji vyvolá samotné běhové prostředí
Silverlightu při násilném “tombstoningu”, jak jsem poznamenal na začátku tohoto článku.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Rozhraní &lt;em&gt;IActivated&lt;/em&gt; s metodou &lt;strong&gt;Activate &lt;/strong&gt;a&lt;strong&gt; &lt;/strong&gt;rozhraní&lt;strong&gt; &lt;/strong&gt;&lt;em&gt;IDeactivated &lt;/em&gt;s
metodou &lt;strong&gt;Deactivate&lt;/strong&gt; ve &lt;em&gt;ViewModelBase&lt;/em&gt; mají jen prázdnou implementaci
a čekají na to, jakou logiku do nich vloží odvozené třídy. Mimochodem&amp;nbsp; – na tomto
místě bychom měli poprvé vytušit, že budeme potřebovat “hostitele” našich view modelů,
který bude vědět, kdy volat metody &lt;em&gt;Activate&lt;/em&gt;, &lt;em&gt;Deactivate&lt;/em&gt;, &lt;em&gt;Init&lt;/em&gt; a
další.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
Třída ViewModelBase explicitně implementuje rozhraní &lt;em&gt;ITransientStateManager&lt;/em&gt;,
které jsme si zavedli pro podporu automatického ukládání a nahrávání tranzientního
stavu. Metody &lt;em&gt;LoadState&lt;/em&gt; a &lt;em&gt;SaveState&lt;/em&gt; ale po svém vyvolání jen předají
řízení chráněným virtuálním metodám &lt;em&gt;DoInternalLoadTransientState&lt;/em&gt; a &lt;em&gt;DoInternalSaveTransientState, &lt;/em&gt;aby
dali šanci i odvozeným třídám změnit způsob uložení a nahrání tranzientního stavu,
i když odvozené třídy jsou většinou spokojeni s tím, že to za ně zvládne předek ViewModelBase.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;script src="https://gist.github.com/745208.js"&gt; &lt;/script&gt;
&lt;p&gt;
Třída ViewModelBase ve svém statickém konstruktoru dosazuje výchozí objekt podporující
rozhraní &lt;em&gt;ITransientStateHelper&lt;/em&gt;, které je klíčové pro uložení a obnovení tranzientního
stavu view modelů a na které delegují i metody &lt;em&gt;DoInternalLoadTransientState&lt;/em&gt;&amp;nbsp;
a &lt;em&gt;DoInternalSaveTransientState&lt;/em&gt; v předchozím výpisu.
&lt;/p&gt;
&lt;p&gt;
Všimněte si, že metoda &lt;em&gt;DoInternalLoadTransientState &lt;/em&gt;po obnovení tranzientního
stavu zkontroluje, jestli se dá view model používat, a pokud ne, zavolá i v této fázi
metodu Init.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;if (!CanUseModel)&lt;br&gt;
{&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&amp;nbsp; Init();&lt;br&gt;
}&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
A nyní se podíváme na mocné rozhraní &lt;em&gt;ITransientStateHelper&lt;/em&gt;
&lt;/p&gt;
&lt;strong&gt;&lt;/strong&gt;&lt;script src="https://gist.github.com/745212.js"&gt; &lt;/script&gt;
&lt;p&gt;
Je asi zřejmé, že metoda &lt;em&gt;GetTransientState&lt;/em&gt; vrátí v objektu Dictionary tranzientní
stav objektu, který jí byl předán v argumentu obj. Metoda &lt;em&gt;RestoreTransientState&lt;/em&gt; naopak
obnoví tranzientní stav objektu v argumentu obj hodnotami v argumentu savedState.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;IsTransientStateEnabledForObject&lt;/em&gt; zjistí, jestli je možné z předaného
objektu získat tranzientní stav. Jak uvidíme, odvozené view modely mohou odmítnout
uložení tranzientního stavu a kdekoli v aplikaci&amp;nbsp; můžeme jejich rozhodnutí jednoduše
zjistit předáním instance view modelu této metodě.
&lt;/p&gt;
&lt;p&gt;
Zde je jedna z možných realizací rozhraní IStateTransientStateHelper, kterou používá
i naše třída ViewModelBase.
&lt;/p&gt;
&lt;script src="https://gist.github.com/745247.js"&gt; &lt;/script&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;p&gt;
Odpovědnosti metod &lt;em&gt;GetTransientState&lt;/em&gt; a &lt;em&gt;RestoreTransientState&lt;/em&gt; jsem
již popsal, nyní jen zmíním pár specialitek v kódu třídy TransientStateHelper.
&lt;/p&gt;
&lt;p&gt;
Metoda GetTransientState zjistí, jestli předaný objekt&amp;nbsp; má tranzientní stav tak,
že zavolá metodu &lt;strong&gt;IsTransientStateEnabledForObject(obj)&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
Metoda IsTransientStateEnabledForObject kontroluje, jestli třída, ze které objekt
pochází, nezakázala vydání tranzientního stavu tím, že je na ní aplikován atribut
[NonTransientState].
&lt;/p&gt;
&lt;p&gt;
Atribut NonTransientState
&lt;/p&gt;
&lt;script src="https://gist.github.com/745279.js"&gt; &lt;/script&gt;
&lt;p&gt;
Atribut NonTransientState může být aplikován nejen na celou třídu, ale i na jednotlivé
vlastnosti objektu, které nemají být součástí tranzientního stavu.&amp;nbsp; &lt;strong&gt;Metoda
GetTransientState neukládá celé view modely, ale s využitím reflexe jen hodnoty jejich
vlastností. Atribut NonTransientState dovoluje vyřadit vlastnosti, které v tranzientním
stavu view modelu nemají co dělat.&lt;/strong&gt; To ale není vše – přímo metoda GetTransientState
dle jmenné konvence vyřadí všechny vlastnosti, jejichž suffix je v poli IGNORE_METHOD_SUFFIX_LIST 
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;public static readonly IEnumerable&lt;string&gt;
IGNORE_METHOD_SUFFIX_LIST = new[] { "Command", "Action", "Helper", "Service", "SynchContext"};
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Do tranzientního stavu se tak nedostanou ve view modelech se často nacházející, ale
s tranzientním stavem view modelu nic nemající a navíc většinou neserializovatelné
objekty jako jsou objekty ICommand (vlastnost Select&lt;strong&gt;Command&lt;/strong&gt;, Save&lt;strong&gt;Command&lt;/strong&gt;),
delegáti&amp;nbsp; TextboxTextChanged&lt;strong&gt;Action&lt;/strong&gt;, služby (ILogger&lt;strong&gt;Service&lt;/strong&gt;)
a další.
&lt;/p&gt;
&lt;p&gt;
Metoda &lt;em&gt;RestoreTransientState&lt;/em&gt; obnoví tranzientní stav objektu. Za zmínku stojí,
že když je předaný objekt potomkem PropertyNotificationBase, tak nastavením vlastnosti
notificationBase.SuppressPropertyChangedNotification na true potlačíme dočasně vyvolání
události OnPropertyChanged, protože je vhodné, abychom událost nevyvolávali, když
view model neobsahuje všechna data a nevíme, kdo všechno na událost reaguje a jaká
další, nyní ve view modelu se nenacházející data, by chtěl načíst. Jak jsem ale psal
v požadavcích na začátku článku, view model nemusí podporovat žádná rozhraní, nemusí
být potomkem ViewModelBase ani PropertyNotificationBase, a proto si ani dědění z PropertyNotificationBase
v této metodě nevynucujeme. Poté, co metoda &lt;em&gt;RestoreTransientState &lt;/em&gt;obnoví
hodnoty všech vlastností, má TransientStateHelper povinnost notifikovat okolí o změně
hodnot všech vlastností view modelu. Jestliže je objekt s obnoveným tranzientním stavem
potomkem PropertyNotificationBase, zavoláme metodu RaisePropertiesChanged(propertyNames.ToArray()),
jinak se metoda &lt;em&gt;RestoreTransientState&lt;/em&gt; pokusí dohledat opět za pomoci reflexe
na objektu metodu nazvanou RaisePropertyChangedEvent, která přijímá název vlastnosti
a kterou použije pro hromadnou distribuci událostí OnPropertyChanged.
&lt;/p&gt;
&lt;p&gt;
Ovládací prvky obsažené (nejen) v control toolkitu jsou&amp;nbsp; přecitlivělé na pořadí
vyvolávání události, a proto jsou vlastnosti seřazeny nyní tak, aby vlastnosti začínající
slovem &lt;em&gt;Selected&lt;/em&gt;&lt;strong&gt; &lt;/strong&gt;vyvolávaly událost OnPropertyChanged jako
poslední. Máte-li ve view modelu kolekci nazvanou Orders (všechny objednávky) a SelectedOrder
(vybraná objednávka z této kolekce), je zaručeno, že &lt;strong&gt;událost OnPropertyChanged
pro vlastnost SelectedOrder bude vyvolána až po události OnPropertyChanged pro vlastnost
Orders.&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Prefixy vlastností, které mají vyvolávat události jako poslední, jsou v proměnné
LAST_SET_VALUE_METHOD_PREFIX. Tyto vlastnosti jsou označeny příznakem LastInit z enumerace
PropertyType.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;public static readonly IEnumerable&lt;string&gt;
LAST_SET_VALUE_METHOD_PREFIX = new[] { "Selected" };
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
To by pro dnešek k třídě ViewModelBase a jejím pomocníkům stačilo:
&lt;/p&gt;
&lt;p&gt;
Příště se podíváme hlavně na “hostitele” view modelů, který by měl být schopen:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Volat na view modelech ve “správnou dobu” metody Init, LoadState, SaveState, Activate,
Deactivate. 
&lt;br&gt;
&lt;li&gt;
Připojit view modely k view (stránce).&lt;br&gt;
&lt;li&gt;
Náš hostitel bude podporovat i více view modelů na jedné stránce, včetně “dědění”
a sdílení použitých view modelů mezi různými view na stránce.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
A také si příště vysvětlíme, proč při získání tranzientního stavu ve ViewModelbase
místo objektu Dictionary používáme vlastní třídu KnownTypesDictionary. Jak možná tušíte,
i název “KnownTypes” odkazuje k tomu, že mají-li být hodnoty uložené v tranzientním
stavu serializovatelné, tak &lt;em&gt;DataContractSerializer,&lt;/em&gt; používaný infrastrukturou
WP7 k serializaci tranzientního stavu, musíme přesvědčit, že v objektu Dictionary
jsou jen objekty z jemu “známých” tříd.
&lt;/p&gt;
&lt;p&gt;
Předcházející články:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx"&gt;Tipy
pro Windows Phone 7 aplikace I&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=060fbd09-0368-4733-92ad-aaecf48409a4" /&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,060fbd09-0368-4733-92ad-aaecf48409a4.aspx</comments>
      <category>C#</category>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=131d4068-9718-43a6-abea-0651f8c8c790</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,131d4068-9718-43a6-abea-0651f8c8c790.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,131d4068-9718-43a6-abea-0651f8c8c790.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=131d4068-9718-43a6-abea-0651f8c8c790</wfw:commentRss>
      <title>Tipy pro Windows Phone 7 aplikace I</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,131d4068-9718-43a6-abea-0651f8c8c790.aspx</guid>
      <link>http://blog.renestein.net/Tipy+Pro+Windows+Phone+7+Aplikace+I.aspx</link>
      <pubDate>Mon, 06 Dec 2010 09:57:19 GMT</pubDate>
      <description>První slíbený článek na téma vývoje Windows Phone 7 aplikací je venku. Dnes si ukážeme většinou kód, který řeší některé od CTP  se vlekoucí chyby ve WP7 SDK, nebo řeší některé nedomyšlenosti a omezení mobilní verze Silverlightu. Mobilní verze Silverlightu vychází totiž ze Silverlightu 3, i když se objevují náznaky, že v lednu přijde aktualizace, která z WP7 udělá zase o něco lepší systém. Nezbývá než doufat, že sousloví “pořádná aktualizace” neoznačuje jen dodání “Copy-Paste” za zvuků fanfár.&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=131d4068-9718-43a6-abea-0651f8c8c790"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,131d4068-9718-43a6-abea-0651f8c8c790.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Silverlight</category>
      <category>WP7</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=2228b31b-1e49-4927-ba1e-1a33c1418142</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,2228b31b-1e49-4927-ba1e-1a33c1418142.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,2228b31b-1e49-4927-ba1e-1a33c1418142.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=2228b31b-1e49-4927-ba1e-1a33c1418142</wfw:commentRss>
      <title>Doplněn&amp;iacute; metod FillPie a DrawPie do objektu Graphics v Compact .Net Frameworku</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,2228b31b-1e49-4927-ba1e-1a33c1418142.aspx</guid>
      <link>http://blog.renestein.net/Dopln%c4%9bniacute+Metod+FillPie+A+DrawPie+Do+Objektu+Graphics+V+Compact+Net+Frameworku.aspx</link>
      <pubDate>Fri, 12 Feb 2010 12:17:54 GMT</pubDate>
      <description>Compact .Net Framework sice nemá metodu FillPie ani DrawPie, ale má obecné metody DrawPolygon a FillPolygon, se kterými nakreslíte, co se vám zlíbí.  Zhýrale jsem kód opět trochu zlinqovatěl, asi začínám být na LINQu a extenzních metodách závislý. Inu, jak říkáme my C# vývojáři, původně odříkané extenzní metody plný zásobník volání. :-)&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=2228b31b-1e49-4927-ba1e-1a33c1418142"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,2228b31b-1e49-4927-ba1e-1a33c1418142.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>LINQ</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=6919d89d-efc3-44fc-9ed8-01530d0e51a9</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,6919d89d-efc3-44fc-9ed8-01530d0e51a9.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,6919d89d-efc3-44fc-9ed8-01530d0e51a9.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=6919d89d-efc3-44fc-9ed8-01530d0e51a9</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <title>Projekt C# Posterous API &amp;ndash; verze 0.0.0.1 Alfa</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,6919d89d-efc3-44fc-9ed8-01530d0e51a9.aspx</guid>
      <link>http://blog.renestein.net/Projekt+C+Posterous+API+Ndash+Verze+0001+Alfa.aspx</link>
      <pubDate>Fri, 15 Jan 2010 16:49:51 GMT</pubDate>
      <description>Jak jsem avizoval minulý týden na twitteru, píšu C# wrapper webového API zajímavé služby Posterous.
Pár odkazů na začátek:
Jestliže nevíte, co je Posterous...
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=6919d89d-efc3-44fc-9ed8-01530d0e51a9"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,6919d89d-efc3-44fc-9ed8-01530d0e51a9.aspx</comments>
      <category>.NET Framework</category>
      <category>C# Posterous API</category>
      <category>Compact .Net Framework</category>
      <category>Silverlight</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea</wfw:commentRss>
      <title>Vynucen&amp;iacute; si překreslen&amp;iacute; cel&amp;eacute; obrazovky v Compact .Net Frameworku</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea.aspx</guid>
      <link>http://blog.renestein.net/Vynuceniacute+Si+P%c5%99ekresleniacute+Celeacute+Obrazovky+V+Compact+Net+Frameworku.aspx</link>
      <pubDate>Wed, 18 Nov 2009 14:02:51 GMT</pubDate>
      <description>Při snaze kreslit grafické objekty na celou obrazovku PDA, a ne pouze na vlastní formulář, se můžete velmi často setkat s dotazem, jak zajistím, že předchozí nakreslené dílko, rozprostřené většinou přes vícero formulářů a mimo naši přímou kontrolu, smažu před vykreslením dalšího dílka. Následující příklad je reakcí na takový dotaz. Za “celou obrazovkou” budeme v článku považovat grafický kontext vrácený voláním metody GetDC s argumentem NULL. Po celé obrazovce PDA je postupně vykreslován kruh (s velkou fantazií míč) pohybující se z levé strany displeje na pravou.&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,b76bc78f-9c0b-46ee-8546-57b8dc4ea2ea.aspx</comments>
      <category>Compact .Net Framework</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=b618d092-145e-45c9-9977-da4d957d3b64</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,b618d092-145e-45c9-9977-da4d957d3b64.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,b618d092-145e-45c9-9977-da4d957d3b64.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=b618d092-145e-45c9-9977-da4d957d3b64</wfw:commentRss>
      <title>Odchytnut&amp;iacute; zpr&amp;aacute;vy WM_KEYDOWN v dialogu &amp;ndash; Windows Mobile</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,b618d092-145e-45c9-9977-da4d957d3b64.aspx</guid>
      <link>http://blog.renestein.net/Odchytnutiacute+Zpraacutevy+WMKEYDOWN+V+Dialogu+Ndash+Windows+Mobile.aspx</link>
      <pubDate>Mon, 27 Jul 2009 10:29:07 GMT</pubDate>
      <description>V jednom předchozím článku jsem slíbil, že na blog dám i kód, který umožní ve Windows dialogu zachytit všechny stisknuté klávesy. Jak možná víte, dialog ve Windows je běžné okno (Window) s třídou (class) WC_DIALOG. K dialogu je přiřazena speciální funkce WNDPROC, která zajišťuje ...&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b618d092-145e-45c9-9977-da4d957d3b64"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,b618d092-145e-45c9-9977-da4d957d3b64.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Nativní kód</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=5fb56cb3-9933-49c9-bca5-f97661795666</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,5fb56cb3-9933-49c9-bca5-f97661795666.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,5fb56cb3-9933-49c9-bca5-f97661795666.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=5fb56cb3-9933-49c9-bca5-f97661795666</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <title>Drobn&amp;aacute; pozn&amp;aacute;mka ke kontravarianc&amp;iacute; deleg&amp;aacute;tů v C#</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,5fb56cb3-9933-49c9-bca5-f97661795666.aspx</guid>
      <link>http://blog.renestein.net/Drobnaacute+Poznaacutemka+Ke+Kontravarianciacute+Delegaacutet%c5%af+V+C.aspx</link>
      <pubDate>Fri, 24 Apr 2009 10:57:02 GMT</pubDate>
      <description>Předpokládám, že se stejně jako já těšíte na lepší podporu kovariance a kontravariance u rozhraní a delegátů v připravované verzi  C# 4.0. Už dnes se ale dá s existující podporou kovariance a kontravariance u delegátů pěkně kouzlit – pro ty s exaktnějším přístupem ke kódu a vytříbenou terminologií se slovo “kouzlit” v knihách zásadně překládá jako “psát elegantnější kód”. Opakovat základy kovariance a kontravariance u delegátů zde nebudu a &lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=5fb56cb3-9933-49c9-bca5-f97661795666"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,5fb56cb3-9933-49c9-bca5-f97661795666.aspx</comments>
      <category>.NET Framework</category>
      <category>Compact .Net Framework</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=94b07439-6cc3-4a9b-864d-fdb27556258e</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,94b07439-6cc3-4a9b-864d-fdb27556258e.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,94b07439-6cc3-4a9b-864d-fdb27556258e.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=94b07439-6cc3-4a9b-864d-fdb27556258e</wfw:commentRss>
      <slash:comments>8</slash:comments>
      <title>Windows Mobile formul&amp;aacute;ř přes cel&amp;yacute; displej - v nativn&amp;iacute;m k&amp;oacute;du</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,94b07439-6cc3-4a9b-864d-fdb27556258e.aspx</guid>
      <link>http://blog.renestein.net/Windows+Mobile+Formulaacute%c5%99+P%c5%99es+Celyacute+Displej+V+Nativniacutem+Koacutedu.aspx</link>
      <pubDate>Tue, 14 Apr 2009 14:04:43 GMT</pubDate>
      <description>Na MSDN fórech jsem si všiml, že se vícekrát objevil dotaz, jak v nativním kódu vytvořit okno přes celou obrazovku, které se bude chovat jako formulář v Compact .Net Framework aplikaci při nastavení vlastnosti WindowState = Maximized.

API SHFullScreen sice přepne okno do celoobrazovkového režimu, ale při zobrazení SIPu se opět objeví taskbar. Při skrytí SIPu se okno vrátí do celoobrazovkového režimu. První, co mě napadlo, je skrýt samotný taskbar. Idea dobrá, mohli jsme mít jednoduché řešení,  ale autoři Windows Mobile jako již tradičně řekli ne...&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=94b07439-6cc3-4a9b-864d-fdb27556258e"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,94b07439-6cc3-4a9b-864d-fdb27556258e.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Nativní kód</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=dc4df303-bc27-4d9c-b817-0ca84fea8825</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,dc4df303-bc27-4d9c-b817-0ca84fea8825.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,dc4df303-bc27-4d9c-b817-0ca84fea8825.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=dc4df303-bc27-4d9c-b817-0ca84fea8825</wfw:commentRss>
      <title>LINQ a logov&amp;aacute;n&amp;iacute; na př&amp;iacute;kladu logov&amp;aacute;n&amp;iacute; kroků Dijsktrova algoritmu</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,dc4df303-bc27-4d9c-b817-0ca84fea8825.aspx</guid>
      <link>http://blog.renestein.net/LINQ+A+Logovaacuteniacute+Na+P%c5%99iacutekladu+Logovaacuteniacute+Krok%c5%af+Dijsktrova+Algoritmu.aspx</link>
      <pubDate>Tue, 03 Mar 2009 15:34:35 GMT</pubDate>
      <description>Na LINQu je pěkné, jak jednoduše můžeme LINQ výraz upravit nebo jej bezbolestně rozšířit o další části. Nedávno jsem publikoval článek Dijsktrův alogritmus pomocí LINQu, extenzních metod a lambda výrazů a nyní si ukážeme drobnou úpravu v kódu, která způsobí, že se před každým rekurzivním voláním vždy vypíšou i prozatímní výsledky hledání nejkratší cesty.



Abychom mohli zalogovat výsledek, vytvoříme si vlastní extenzní metody pro výpis informací z předaného libovolného generického IEnumerable&lt;T&gt; do ...&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=dc4df303-bc27-4d9c-b817-0ca84fea8825"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,dc4df303-bc27-4d9c-b817-0ca84fea8825.aspx</comments>
      <category>.NET Framework</category>
      <category>Compact .Net Framework</category>
      <category>LINQ</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=b7a67f4e-21e5-4453-aad5-7e1903c18a44</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,b7a67f4e-21e5-4453-aad5-7e1903c18a44.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,b7a67f4e-21e5-4453-aad5-7e1903c18a44.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=b7a67f4e-21e5-4453-aad5-7e1903c18a44</wfw:commentRss>
      <title>N&amp;aacute;hrada ParametrizedThreadStart deleg&amp;aacute;ta v Compact .Net Frameworku</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,b7a67f4e-21e5-4453-aad5-7e1903c18a44.aspx</guid>
      <link>http://blog.renestein.net/Naacutehrada+ParametrizedThreadStart+Delegaacuteta+V+Compact+Net+Frameworku.aspx</link>
      <pubDate>Mon, 02 Mar 2009 12:48:05 GMT</pubDate>
      <description>Na fórech o Compact .Net Frameworku (CNF) se často objevují stesky,  že v CNF třída Thread nemá konstruktor, který by přijímal delegáta ParametrizedThreadStart. Metodě, na kterou ukazuje delegát ParametrizedThreadStart a která bude spuštěna v novém threadu, můžeme předat jeden argument typu object .

public delegate void ParametrizedThreadStartDelegate(Object obj);



Ty nářky jsou liché, protože můžeme  předat do konstruktoru odkaz na instanční metodu bez argumentů ve vlastním objektu, který má ve svých proměnných na úrovni třídy nebo vlastnostech stavové informace, které použije instanční metoda poté, co je zavolána z metody Start threadu.



Pomocí anonymních metod či lambda výrazů se ale zbavíme nutnosti deklarovat vlastní třídu. Lambda výraz funguje jako adaptér...&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=b7a67f4e-21e5-4453-aad5-7e1903c18a44"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,b7a67f4e-21e5-4453-aad5-7e1903c18a44.aspx</comments>
      <category>Compact .Net Framework</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=19e20d35-6660-4911-b640-d666aed87aba</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,19e20d35-6660-4911-b640-d666aed87aba.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,19e20d35-6660-4911-b640-d666aed87aba.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=19e20d35-6660-4911-b640-d666aed87aba</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Dijsktrův alogritmus pomoc&amp;iacute; LINQu, extenzn&amp;iacute;ch metod a lambda v&amp;yacute;razů</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,19e20d35-6660-4911-b640-d666aed87aba.aspx</guid>
      <link>http://blog.renestein.net/Dijsktr%c5%afv+Alogritmus+Pomociacute+LINQu+Extenzniacutech+Metod+A+Lambda+Vyacuteraz%c5%af.aspx</link>
      <pubDate>Wed, 11 Feb 2009 18:13:14 GMT</pubDate>
      <description>Pokusil jsem se napsat Dijsktrův algoritmus pomocí LINQ konstrukcí. Pokud někdo z vás tápe, k čemu je Dijsktrův algoritmus dobrý a k čemu slouží, odkážu jej na podrobný článek na Wikipedii. Zde jen připomenu, že Dijsktrův algoritmus slouží k nalezení nejkratších cest v grafu z jednoho zdrojového uzlu ke všem ostatním uzlům. Je tak možné najít například nejkratší cestu z jednoho města do druhého. Na internetu jsem našel jeden graf, který budeme mít stále před očima a na který budeme Dijkstrův algoritmus napsaný v LINQu aplikovat.&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=19e20d35-6660-4911-b640-d666aed87aba"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,19e20d35-6660-4911-b640-d666aed87aba.aspx</comments>
      <category>.NET Framework</category>
      <category>Compact .Net Framework</category>
      <category>LINQ</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=0de5237c-9c45-41bd-9297-0952ba7954f0</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,0de5237c-9c45-41bd-9297-0952ba7954f0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,0de5237c-9c45-41bd-9297-0952ba7954f0.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=0de5237c-9c45-41bd-9297-0952ba7954f0</wfw:commentRss>
      <slash:comments>6</slash:comments>
      <title>Textbox nepodporuj&amp;iacute;c&amp;iacute; v&amp;yacute;běr textu a dal&amp;scaron;&amp;iacute; specialitky</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,0de5237c-9c45-41bd-9297-0952ba7954f0.aspx</guid>
      <link>http://blog.renestein.net/Textbox+Nepodporujiacuteciacute+Vyacuteb%c4%9br+Textu+A+Dalscaroniacute+Specialitky.aspx</link>
      <pubDate>Wed, 04 Feb 2009 15:52:26 GMT</pubDate>
      <description>Někdy se hodí mít textbox, u kterého je skrytý "caret" (netuší někdo, jak se termín caret překládá - pouze kurzor?) a současně nepodporuje označování textu. Také můžete chtít, aby se textbox choval podobně jako při nastavení vlastnosti ReadOnly na true, ale bez "zašedlého" zobrazení textboxu, což je  většinou nechtěný průvodní jev textových polí označených pouze pro čtení.&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=0de5237c-9c45-41bd-9297-0952ba7954f0"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,0de5237c-9c45-41bd-9297-0952ba7954f0.aspx</comments>
      <category>.NET Framework</category>
      <category>Compact .Net Framework</category>
      <category>Nativní kód</category>
      <category>Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=56334b10-44b9-4d92-a742-b5e9bbc9e79c</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,56334b10-44b9-4d92-a742-b5e9bbc9e79c.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,56334b10-44b9-4d92-a742-b5e9bbc9e79c.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=56334b10-44b9-4d92-a742-b5e9bbc9e79c</wfw:commentRss>
      <title>Lehk&amp;aacute; imitace někter&amp;yacute;ch rysů windows forms aplikac&amp;iacute; v non-windows forms aplikac&amp;iacute;ch</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,56334b10-44b9-4d92-a742-b5e9bbc9e79c.aspx</guid>
      <link>http://blog.renestein.net/Lehkaacute+Imitace+N%c4%9bkteryacutech+Rys%c5%af+Windows+Forms+Aplikaciacute+V+Nonwindows+Forms+Aplikaciacutech.aspx</link>
      <pubDate>Mon, 02 Feb 2009 13:51:15 GMT</pubDate>
      <description>Omluvte prosím trochu kryptický název, ale lepší a hlavně výstižnější pojmenování článku mě nenapadlo. Název je stejně jen vábnička na čtenáře, proto se podívejme, co je jím míněno.

Již několikrát mně různí vývojáři tvrdili, jak nepříjemná je pro ně práce s konzolí (windows službou, dosaďte další typy aplikací dle libosti...), protože musí řešit, aby aplikace po svém spuštění ihned neskončila, a také je pro ně problematické zajistit, aby byly některé události zpracovány vždy ve stejném threadu.

Převedeme-li emocionální stížnost do věcného jazyka, zjistíme, že to, co v těchto typech aplikací chybí, jsou následující rysy běžné windows forms aplikace:&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=56334b10-44b9-4d92-a742-b5e9bbc9e79c"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,56334b10-44b9-4d92-a742-b5e9bbc9e79c.aspx</comments>
      <category>.NET Framework</category>
      <category>Compact .Net Framework</category>
      <category>Návrhové vzory</category>
      <category>Windows Forms</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=c45e480d-5738-4669-99af-15aebb87daa1</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,c45e480d-5738-4669-99af-15aebb87daa1.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,c45e480d-5738-4669-99af-15aebb87daa1.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=c45e480d-5738-4669-99af-15aebb87daa1</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Odhl&amp;aacute;&amp;scaron;en&amp;iacute; uživatele z aplikace po uplynut&amp;iacute; nastaven&amp;eacute; doby</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,c45e480d-5738-4669-99af-15aebb87daa1.aspx</guid>
      <link>http://blog.renestein.net/Odhlaacutescaroneniacute+U%c5%beivatele+Z+Aplikace+Po+Uplynutiacute+Nastaveneacute+Doby.aspx</link>
      <pubDate>Mon, 12 Jan 2009 12:56:25 GMT</pubDate>
      <description>Jedním z požadavků na Pocket PC (Windows Mobile ) aplikace je  odhlášení uživatele po uplynutí stanovené doby, kdy s aplikací nepracoval, aby se zmenšilo riziko, že uživatel někde PDA položí, někdo jiný PDA  najde a ochutná z gurmánského menu  položku "co nám dnes servírují za citlivé údaje" nebo  se vrhne na žertovné a bezrizikové mazání dat na serveru pod identitou nenáviděného kolegy. Tedy alespoň nějak takto si představuji důvody, kvůli kterým zákazníci na automatickém odhlašování tak lpějí. :) ...&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=c45e480d-5738-4669-99af-15aebb87daa1"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,c45e480d-5738-4669-99af-15aebb87daa1.aspx</comments>
      <category>Compact .Net Framework</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=3b700e20-c592-4da6-984b-bc70294eb78b</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,3b700e20-c592-4da6-984b-bc70294eb78b.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,3b700e20-c592-4da6-984b-bc70294eb78b.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=3b700e20-c592-4da6-984b-bc70294eb78b</wfw:commentRss>
      <slash:comments>4</slash:comments>
      <title>Extenzn&amp;iacute; metoda - bin&amp;aacute;rn&amp;iacute; operace And pro enumerace</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,3b700e20-c592-4da6-984b-bc70294eb78b.aspx</guid>
      <link>http://blog.renestein.net/Extenzniacute+Metoda+Binaacuterniacute+Operace+And+Pro+Enumerace.aspx</link>
      <pubDate>Sun, 21 Dec 2008 11:22:20 GMT</pubDate>
      <description>V diskuzním fóru se (po dlouhé době :-)) objevil jeden zajímavější dotaz, který se netýká ani toho, jak zobrazit druhý formulář v aplikaci, ba ani autor nebojuje s mizením dat po postbacku v ASP.NET aplikaci.

Ale vážně - autor dotazu by chtěl mít lepší syntaxi pro binární operaci And v enumeracích označených metaatributem Flags. Mně stávající C syntaxe (Rights &amp; Rights.Add == Rights.Add) zcela vyhovuje a žádný další syntaktický cukřík hltat nechci,  ale přesto mě zaujalo, jak by se dal problém, tedy spíš estetická preference náročného tazatele :-),  řešit.
&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=3b700e20-c592-4da6-984b-bc70294eb78b"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,3b700e20-c592-4da6-984b-bc70294eb78b.aspx</comments>
      <category>.NET Framework</category>
      <category>Compact .Net Framework</category>
      <category>LINQ</category>
    </item>
    <item>
      <trackback:ping>http://blog.renestein.net/Trackback.aspx?guid=5605d333-0313-4681-9528-61fb71e121a0</trackback:ping>
      <pingback:server>http://blog.renestein.net/pingback.aspx</pingback:server>
      <pingback:target>http://blog.renestein.net/PermaLink,guid,5605d333-0313-4681-9528-61fb71e121a0.aspx</pingback:target>
      <dc:creator>
      </dc:creator>
      <wfw:comment>http://blog.renestein.net/CommentView,guid,5605d333-0313-4681-9528-61fb71e121a0.aspx</wfw:comment>
      <wfw:commentRss>http://blog.renestein.net/SyndicationService.asmx/GetEntryCommentsRss?guid=5605d333-0313-4681-9528-61fb71e121a0</wfw:commentRss>
      <title>Běh aplikace na Windows Mobile při vypnut&amp;eacute;m displeji a opětovn&amp;eacute; probuzen&amp;iacute; zař&amp;iacute;zen&amp;iacute;</title>
      <guid isPermaLink="false">http://blog.renestein.net/PermaLink,guid,5605d333-0313-4681-9528-61fb71e121a0.aspx</guid>
      <link>http://blog.renestein.net/B%c4%9bh+Aplikace+Na+Windows+Mobile+P%c5%99i+Vypnuteacutem+Displeji+A+Op%c4%9btovneacute+Probuzeniacute+Za%c5%99iacutezeniacute.aspx</link>
      <pubDate>Mon, 01 Dec 2008 17:23:53 GMT</pubDate>
      <description>Jedním z problémů, se kterými se vývojáři často potýkají, je, že PDA (přesněji Windows Mobile Professional a Classic zařízení  - zařízení s dotykovým displejem) na rozdíl od Smartphonu (Windows Mobile Standard) po uplynutí doby nastavené v ovládacích panelech přecházejí do stavu "Off" (přesněji do stavu "Suspended" dle oficiální terminologie, stav Off má pouze Smartphone - my ale budeme dále ve spotu používat termín "off") , v němž  je provádění kódu aplikace zcela "zmrazeno". Aplikace jsou "hibernovány" a můžeme je považovat za dočasné mrtvolky.

Občas potřebujeme, aby sice došlo k vypnutí displeje zařízení a my tak drasticky a navíc zbytečně neredukovali výdrž baterie, ale aby naše aplikace na pozadí stále běžela. To je první  požadavek. Dalším z častých požadavků je schopnost aplikace probudit celé zařízení ze stavu "off".&lt;img width="0" height="0" src="http://blog.renestein.net/aggbug.ashx?id=5605d333-0313-4681-9528-61fb71e121a0"/&gt;</description>
      <comments>http://blog.renestein.net/CommentView,guid,5605d333-0313-4681-9528-61fb71e121a0.aspx</comments>
      <category>Compact .Net Framework</category>
      <category>Mobilitky</category>
    </item>
  </channel>
</rss>