<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" 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:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Smart Client</title>
        <link>http://geekswithblogs.net/kobush/category/3702.aspx</link>
        <description>Including Composite UI Application Block and other topics related to developing Smart Clients.</description>
        <language>pl-PL</language>
        <copyright>Szymon Kobalczyk</copyright>
        <managingEditor>skobalczyk@gmail.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>How I won the Lab49 WPF in Finance Innovation Contest?</title>
            <link>http://geekswithblogs.net/kobush/archive/2008/03/17/120601.aspx</link>
            <description>&lt;p&gt;&lt;img style="margin: 0px 0px 5px 5px" src="http://www.lab49.com/files/logos/wpf_logo_blue3.gif" align="right" /&gt;Honestly, I still don't know how I did it. The LAB49 &lt;a href="http://wpfcontest.lab49.com/"&gt;WPF in Finance Innovation Contest&lt;/a&gt; was announced back in December and I think I first read about it on &lt;a href="http://blogs.msdn.com/tims/archive/2007/12/04/wpf-and-silverlight-contest-season-is-here.aspx"&gt;Tim Sneath blog&lt;/a&gt;. With &lt;a href="http://wpfcontest.lab49.com/prizes.aspx"&gt;all the cool prizes&lt;/a&gt; I was very inclined to participate, but it quickly turned out that its available only to US citizens. However that changed in the first week of February, so I started considering it again, but still didn't had any clue what to do. You see the goal of this contest was to create a WPF application that visualizes a set of provided financial data in some interesting way. While the first part was easy (writing the app in WPF) the hardest part was to figure out what to do with the data. Only after "last call to action" email from Daniel Chait I decided its about time to start coding.&lt;/p&gt; &lt;p&gt;Because I started working late on this project, initially I wanted to create only a charting control capable of displaying the line and candlestick plot of stock prices. But after the contest deadline was extended I started thinking of a better way to visualize the stock prices for a given day – something that goes beyond a simple listbox or a datagrid. The next option I considered was to create a heatmap – i.e. use color gradients to denote the change in stock prices relative to the previous day. But in all samples I’ve seen these symbols were placed on a regular grid and the placement didn’t correspond in any particular way with the data. I started thinking about how to sort the symbols so that those that experienced similar data change would be close to each other, and those with different data change remain further apart. This finally led me to the idea of applying &lt;a href="http://www.red3d.com/cwr/boids/"&gt;Craig Reynolds’ flocking algorithm&lt;/a&gt; to perform this clustering.  &lt;/p&gt;&lt;p&gt;Here is a screenshot from my final entry called &lt;strong&gt;Stock Information Boids&lt;/strong&gt;:  &lt;/p&gt;&lt;p align="center"&gt; &lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/kobush/WindowsLiveWriter/HowIwontheLab49WPFinFinanceInnovationCon_11EC2/image_4.png"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="480" alt="Stock Information Boids WPF Application" src="http://geekswithblogs.net/images/geekswithblogs_net/kobush/WindowsLiveWriter/HowIwontheLab49WPFinFinanceInnovationCon_11EC2/image_thumb_1.png" width="591" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Also you can already download the source code for this application from &lt;a href="http://code.msdn.microsoft.com/KobushCode/Release/ProjectReleases.aspx?ReleaseId=667"&gt;my resource page at MSDN Code Gallery&lt;/a&gt;. Make sure to read the user guide that describes how the algorithm works and how to use the application.  &lt;/p&gt;&lt;p&gt;Turns out that for some reason the judges liked my solution, because last week at the closing keynote of 2008 &lt;a href="http://www.financialdevelopers.com"&gt;Microsoft Financial Services Developer Conference&lt;/a&gt; in New York, &lt;a href="http://blog.lab49.com/archives/1888"&gt;Daniel Chait announced&lt;/a&gt; that I won &lt;a href="http://blog.lab49.com/archives/1884"&gt;the grand prize in the contest&lt;/a&gt;!  &lt;/p&gt;&lt;p&gt;The two finalist were &lt;strong&gt;Jacob Carpenter&lt;/strong&gt; and &lt;strong&gt;Jobi K Joy&lt;/strong&gt;, while the honorable mention went to &lt;strong&gt;Paul Hounshell&lt;/strong&gt;. Congratulations guys, great work! You can download their very cool applications from here: &lt;/p&gt; &lt;p&gt;&lt;iframe style="border-right: #dde5e9 1px solid; padding-right: 0px; border-top: #dde5e9 1px solid; padding-left: 0px; padding-bottom: 0px; margin: 3px; border-left: #dde5e9 1px solid; width: 240px; padding-top: 0px; border-bottom: #dde5e9 1px solid; height: 66px; background-color: #ffffff" marginwidth="0" marginheight="0" src="http://cid-5b79e3a01fce9e08.skydrive.live.com/embedrowdetail.aspx/2008%20WPF%20in%20Finance%20Innovation%20Contest" frameborder="0" scrolling="no"&gt;&lt;/iframe&gt;&lt;/p&gt; &lt;p&gt;In following weeks I will try to share some details on my implementations (in particular about the Timeline and Flock controls). I was already told that &lt;a href="http://jobijoy.blogspot.com/"&gt;Jobi K Joy&lt;/a&gt; and &lt;a href="http://jacobcarpenter.wordpress.com/"&gt;Jacob Carpenter&lt;/a&gt; plan to do the same, so make sure to subscribe to their blogs too.  &lt;/p&gt;&lt;p&gt;I would like to thank &lt;a href="http://wpfcontest.lab49.com/judges.aspx"&gt;the judges&lt;/a&gt; for selecting my entry. And last but not least, big kisses for my wife Joanna for letting me work on the project all nights and weekends considering her present condition (L)&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120601"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=120601" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/120601.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2008/03/17/120601.aspx</guid>
            <pubDate>Mon, 17 Mar 2008 20:39:06 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/120601.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2008/03/17/120601.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/120601.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/120601.aspx</trackback:ping>
        </item>
        <item>
            <title>Introducing WikiSpider</title>
            <link>http://geekswithblogs.net/kobush/archive/2008/01/30/119101.aspx</link>
            <description>&lt;p&gt;About two weeks ago &lt;a href="http://www.microsoft.com/poland/developer/kontakt/dbiesiada.mspx"&gt;Daniel Biesiada&lt;/a&gt; (who is ISV DE here in Poland) announced on his blog a little &lt;a href="http://blogs.msdn.com/danieb/archive/2008/01/13/pl-geek-w-spos-b-na-nud-w-tym-konkurs.aspx"&gt;programming contest&lt;/a&gt;. The goal was to build a .NET application that would check if the the theory of &lt;a href="http://en.wikipedia.org/wiki/Six_degrees_of_separation"&gt;Six Degrees of separation&lt;/a&gt; applies to two given topics in Wikipedia. In order words to find a path from the source page to destination with no more then six links. At the time I had not much else to do (apart from setting up website for the &lt;a href="http://www.c2c2008.pl/"&gt;C2C Conference&lt;/a&gt;, helping out with the &lt;a href="http://poland.silverlightchallenge.eu/"&gt;European Silverlight Challenge&lt;/a&gt;, and preparing for the WPF Beta Exam) so I decided to give it a try. &lt;/p&gt; &lt;p&gt;Fast forward two weeks and I present you my WikiSpider:&lt;/p&gt; &lt;p align="center"&gt;&lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="534" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/kobush/WindowsLiveWriter/e10a9ad47337_11C9E/image_3.png" width="600" border="0" /&gt; &lt;/p&gt; &lt;p&gt;As usual building this took me much more time than I initially anticipated (including few sleepless nights). And still I didn't make it before the deadline, so this even didn't count as a contest entry anymore (sigh!). However this was mainly because my personal goal was to throw in there every new piece of .NET 3.5 I could find fit - and most of them I never used before. &lt;/p&gt; &lt;p&gt;Here are some key technologies I managed to put into this:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The UI is done in &lt;strong&gt;WPF&lt;/strong&gt; (and this was the only thing here I knew a bit about). However I borrowed the graph control from the excellent &lt;a href="http://j832.com/BagOTricks/"&gt;Kevin's WPF Bag-o-Tricks&lt;/a&gt;.  &lt;/li&gt;&lt;li&gt;The caching is done using &lt;strong&gt;SQL Server Express&lt;/strong&gt;. Initially I wanted to do this using &lt;strong&gt;SQL Compact &lt;/strong&gt;but I run into performance issues and had to switch to full SQL in order to run the queries in profiler. But since this was fixed (with big help from &lt;a href="http://zine.net.pl/blogs/sqlgeek/"&gt;Paweł Potasiński&lt;/a&gt;) I could try with SQL Compact again.  &lt;/li&gt;&lt;li&gt;Of course data-access is done using &lt;strong&gt;LINQ to SQL&lt;/strong&gt;. And of course this was the main source of my problems, as it was first time I've done anything in it, and so far I only read the &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/08/27/linq-to-sql-part-8-executing-custom-sql-expressions.aspx"&gt;Scott Gu's tutorials&lt;/a&gt;. Still, I'm already in love with it.  &lt;/li&gt;&lt;li&gt;Speaking of LINQ. Initially we were screen scrapping the HTML pages to get all the links.  But turns out that Wikipedia has a little known about &lt;a href="http://en.wikipedia.org/w/query.php"&gt;Query API&lt;/a&gt; that enables to get the page content in XML. So the obvious move was to rewrite this part with &lt;strong&gt;LINQ to XML&lt;/strong&gt;.  &lt;/li&gt;&lt;li&gt;The path-finding algorithm was borrowed from &lt;a href="http://blogs.msdn.com/ericlippert/archive/2007/10/10/path-finding-using-a-in-c-3-0-part-four.aspx"&gt;Eric Lippert&lt;/a&gt;. The nice thing about it is that it uses lots of &lt;strong&gt;C# 3.0 language features&lt;/strong&gt;, so it is a great resource to learn from. The new C# syntax is so addictive that I already miss it in my other project.  &lt;/li&gt;&lt;li&gt;Finally, I wanted to publish the app with ClickOnce but run out of time. So maybe later. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I learned many interesting things and tried out some new stuff that I wanted to check out anyway. I will try to share my discoveries in the next few days, but in the meantime feel free to download and take a look at may code (I know it's not prettiest piece of code you've seen but I was in a rush to finish this on time):&lt;/p&gt; &lt;p&gt;&lt;strong&gt;&lt;a title="SixDegreesOfWikipedia 1.0" href="http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=KobushCode&amp;amp;DownloadId=686"&gt;Download the source code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Here you can also download the entries from other participants: &lt;a href="http://www.dbiesiada.com/projects/WikiPathFinding/wikiContest_LukaszSowa.zip"&gt;Łukasz Sowa&lt;/a&gt;, &lt;a href="http://www.dbiesiada.com/projects/WikiPathFinding/wikiContest_MaciejRutkowski.zip"&gt;Maciej Rutkowski&lt;/a&gt;, and &lt;a href="http://www.dbiesiada.com/projects/WikiPathFinding/WikiContest_ArkadiuszBenedykt.zip"&gt;Arkadiusz Benedykt&lt;/a&gt;. Congratulations to all of you!&lt;/p&gt; &lt;h3&gt;Installation&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;Download the code from the above link and extract it.  &lt;/li&gt;&lt;li&gt;The application uses local SQL database for caching and unfortunately you need to create it yourself (now you know why I wanted to use SQL Compact). Simply launch SSMS and create empty database called WikiCache.  &lt;/li&gt;&lt;li&gt;Run the &lt;strong&gt;Create_WikiCacheDB.sql&lt;/strong&gt; script from the &lt;strong&gt;data &lt;/strong&gt;folder to create the database schema.  &lt;/li&gt;&lt;li&gt;By default the app is configured to look for the &lt;strong&gt;WikiCache &lt;/strong&gt;database on the local &lt;strong&gt;SQLEXPRESS &lt;/strong&gt;instance. If you installed it somewhere else update the connection string in &lt;strong&gt;app.config &lt;/strong&gt;accordingly.  &lt;/li&gt;&lt;li&gt;Run the &lt;strong&gt;build.bat &lt;/strong&gt;or open solution in Visual Studio 2008 and run from there.&lt;/li&gt;&lt;/ol&gt; &lt;h3&gt;Usage&lt;/h3&gt; &lt;ol&gt; &lt;li&gt;Enter the name of the Wikipedia page in the address bar at the top and press the Go! button. The entered topic and the pages it links to will be displayed as graph.  &lt;/li&gt;&lt;li&gt;Clicking on any topic will make it currently selected (put it in the center of the graph).  &lt;/li&gt;&lt;li&gt;Right-click on any topic to open the context menu. Select "&lt;em&gt;Open in browser&lt;/em&gt;" to.... load the page in browser.  &lt;/li&gt;&lt;li&gt;Select "&lt;em&gt;Set as source&lt;/em&gt;" or "&lt;em&gt;Set as destination&lt;/em&gt;" to put the topic name in appropriate field on the sidebar &lt;br /&gt;[Note: &lt;em&gt;Currently it's the only way to show the sidebar&lt;/em&gt;]  &lt;/li&gt;&lt;li&gt;You can also enter the source/destination topics manually.  &lt;/li&gt;&lt;li&gt;When both are set click on the &lt;em&gt;Start &lt;/em&gt;button to begin searching for the path. Few statistics are displayed on the bottom of the sidebar.  &lt;/li&gt;&lt;li&gt;During the search you can still use the graph or navigate to other pages (thanks to the BackgroundWorker magic).  &lt;/li&gt;&lt;li&gt;When path is found it is displayed on the sidebar, and you can click on each topic to center it on graph. &lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Have fun! &lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=119101"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=119101" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/119101.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2008/01/30/119101.aspx</guid>
            <pubDate>Wed, 30 Jan 2008 21:22:47 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/119101.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2008/01/30/119101.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/119101.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/119101.aspx</trackback:ping>
        </item>
        <item>
            <title>White paper: Designing Smart Clients Based on CAB and SCSF</title>
            <link>http://geekswithblogs.net/kobush/archive/2007/01/13/103499.aspx</link>
            <description>&lt;p&gt;A year ago I've published a series of articles on understanding Composite UI Application Block (CAB). Although I've never got to finish it I still occasionally receive comments and questions on this subject.&lt;/p&gt; &lt;p&gt;Recently I came across two great papers on CAB and SCSF that I would like to share:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5F9A8435-1651-4BE2-956D-0446A89A7358&amp;amp;displaylang=en"&gt;Designing Smart Clients Based on CAB and SCSF&lt;/a&gt; by Mario Spuszta, is architectural guidance created for RACON Software GmbH, and later published as white paper on MSDN. It contains complete overview of CAB and SCSF, with many interesting tips on implementation and project management. It&amp;nbsp;answers many question I had when I was learning CAB.&amp;nbsp;What I particularly liked is the use case-driven strategy for identifying work items.  &lt;li&gt;&lt;a href="http://msdn2.microsoft.com/en-us/architecture/bb190159.aspx"&gt;Commonwealth Bank of Australia CommSee Solution: Case Study&lt;/a&gt;. Commonwealth Bank of Australia&amp;nbsp;designed, developed, and implemented its CommSee application, a relationship banking solution custom-built by the Commonwealth Bank of Australia. This &lt;a href="http://www.zdnet.com.au/news/software/soa/CommSee_an_absolute_standout_CBA_chief/0,130061733,139238388,00.htm"&gt;project was major success&lt;/a&gt; and has been successfully deployed to 30,000 users at more than 1,700 sites across Australia.&amp;nbsp;Its architecture inspired patterns&amp;amp;practices implementation of CAB and serves as great source of ideas on building composite smart clients and SOA applications. Ron Jacob recorded series of &lt;a href="http://msdn2.microsoft.com/en-us/architecture/aa948850.aspx"&gt;video interviews with the CommSee core team&lt;/a&gt;&amp;nbsp;available on Channel 9.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=103499"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=103499" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/103499.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2007/01/13/103499.aspx</guid>
            <pubDate>Sat, 13 Jan 2007 10:09:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/103499.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2007/01/13/103499.aspx#feedback</comments>
            <slash:comments>5</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/103499.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/103499.aspx</trackback:ping>
        </item>
        <item>
            <title>Understanding Composite UI Application Block, Part VII</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/02/26/70737.aspx</link>
            <description>&lt;P&gt;There seams to be some confusion around WorkItem's State. I've seen few posts on CAB message boards with questions if it's OK to put certain data into it. I will try to add my two cents to it but note that this is my point of view and it might be wrong.&lt;/P&gt;
&lt;P&gt;Let's think for a minute what kinds of data we can have in our applications. First that comes to mind is the data that is presented to the end-user and this of course must be stored in the View (SmartPart) for the time it's displayed. This data can be loaded from some external sources (files, database) but this should be handled by services. To do their work services can also carry some runtime data that is not visible to the end-user. &lt;/P&gt;
&lt;P&gt;So we have some flow of data between Views and Services (preferably with Controller or Presenter in the middle). But many times we also need to share same data between several Views. This will be for example in classical master-detail scenario when one View presents list of records and the other one shows details of currently selected record. Clearly the information of selected item lays outside of the service's domain because the same service can be used by several Views so from this standpoint it should be &amp;#8220;stateless&amp;#8220;. So here is where WorkItem's state comes in handy. In short State property is a loosely typed collection of items identified by some key. In my understanding it should be primary used for communication between SmartParts and other Items contained within the same WorkItem and its child WorkItems.&lt;/P&gt;
&lt;P&gt;There are several mechanisms in CAB that help us with this scenarios.&lt;/P&gt;
&lt;H3&gt;State change notification&lt;/H3&gt;
&lt;P&gt;Often we want to react somehow to changes in State item's value. CAB automatically publishes events to state changes and allows to declare handlers simply by putting StateChangedAttribute on a method:&lt;/P&gt;&lt;PRE class=csharpcode&gt;[StateChanged(&lt;SPAN class=str&gt;"MyProperty"&lt;/SPAN&gt;)]
&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; MyProperty_StateChanged(&lt;SPAN class=kwrd&gt;object&lt;/SPAN&gt; sender, StateChangedEventArgs args)
{
&lt;SPAN class=rem&gt; // handle state change&lt;/SPAN&gt;
}&lt;/PRE&gt;
&lt;P&gt;The StateChangedEventArgs contain State item's key, and both old and new values. Of course there can be more then one handler to this event. Also check out &lt;A href="http://luifit.net/blogs/jluif/PermaLink,guid,8cf9a782-d629-4f49-ac9b-6d22c8ae9598.aspx"&gt;John Luif's blog entry&lt;/A&gt; on this.&lt;/P&gt;
&lt;H3&gt;Injecting State into child WorkItems &lt;/H3&gt;
&lt;P&gt;Sometimes we need to pass the current value of some State item from parent WorkItem to the newly created child WorkItem. We can do this by manually copying the respective values or let the CAB do the work for us. To indicate that property value or constructor parameter should be injected from parent WorkItem's State we can use the StateAttribute:&lt;/P&gt;&lt;PRE class=csharpcode&gt;[State(&lt;SPAN class=str&gt;"MyProperty"&lt;/SPAN&gt;)]
&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;string&lt;/SPAN&gt; MyChildProperty
{
get { ... }
set { ... }
}&lt;/PRE&gt;
&lt;P&gt;Note that this will only copy the value when child WorkItem is created and won't update it when it changes on parent WorkItem. There are some restrictions when using state injection and be sure to read two excellent entries on &lt;A href="http://staff.southworks.net/blogs/mariano/archive/category/1043.aspx"&gt;Mariano's Szklanny blog&lt;/A&gt; on how to avoid them.&lt;/P&gt;
&lt;H3&gt;Persisting WorkItem's State &lt;/H3&gt;
&lt;P&gt;Finally, CAB defines IStatePersistenceService that allows to persist WorkItem's State between sessions. Out of the box CAB provides to implementations: FileStatePersistenceService and IsolatedStorageStatePersistenceService. Both store state in binary files using the BinaryFormater serializer, but the later one uses Isolated Storage so it should work in restricted access scenarios. Both inherit from StreamStatePersistantService base class with you can also use to implement you own service.&lt;/P&gt;
&lt;P&gt;This service does not load by default and you need to add following entry in app.config to enable it:&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;CompositeUI&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt; &amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;services&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt; &amp;lt;&lt;/SPAN&gt;&lt;SPAN class=html&gt;add&lt;/SPAN&gt; &lt;SPAN class=attr&gt;serviceType&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="Microsoft.Practices.CompositeUI.Services.IStatePersistenceService,
Microsoft.Practices.CompositeUI"&lt;/SPAN&gt; 
&lt;SPAN class=attr&gt; instanceType&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;="Microsoft.Practices.CompositeUI.Services.IsolatedStorageStatePersistenceService,
Microsoft.Practices.CompositeUI"&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;/&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt; &lt;/&lt; SPAN&gt;&lt;SPAN class=html&gt;services&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;
&lt;SPAN class=kwrd&gt;&lt;/&lt; SPAN&gt;&lt;SPAN class=html&gt;CompositeUI&lt;/SPAN&gt;&lt;SPAN class=kwrd&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;To store or retrieve WorkItem's State simply use it's Save() and Load() methods. Note that it uses WorkItem's name to uniquely identify that WorkItem's state so make sure you assign it to the same value before saving and loading. &lt;/P&gt;
&lt;P&gt;I haven't tried this one yet but it opens some interesting possibilities.&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;As example of using state let's take a look at the Inventory WorkItem of my sample application. There are three primary views in this WorkItem: Product list, Items list and Item details. When user selects a product category the first view shows list of products for this category. Next when product is selected second view shows product items. Then after selecting the item it's details are presented on the final view. The IDs of currently selected records are stored in Inventory WorkItem's state and the View's are wired to state change events so they react immediately to any changes.&lt;/P&gt;
&lt;P&gt;Currently only one view is displayed at a time but now we can easily build an "Advanced View" that will show all three views at once. We will start by creating container SmartParts for both modes. SimpleView hosts a DeckWorkspace while AdvancedView contains ZoneWorkspace with two SplitContainers. Both also contain simple link buttons to switch the view. These buttons invoke a TogleValueCommand that changes the value of the ViewMode property. This in turn rises a StateChange event that is handled in ViewMode_StateChanged method. Finally this method changes the current container view and moves the three inventory views to current workspace. It also tries to maintain current active SmartPart. &lt;/P&gt;
&lt;P&gt;You can see the inventory screens in both modes below:&lt;/P&gt;
&lt;CENTER&gt;&lt;IMG src="/images/geekswithblogs_net/kobush/1591/o_inventory.jpg"&gt;&lt;/CENTER&gt;
&lt;P&gt;But the nicest part in all this that I didn't have to change the existing SmartParts at all! They were already communicating with State and changing their arrangement on screen didn't required any changes to their code. Isn't that cool or what :-)&lt;/P&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=70737"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=70737" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/70737.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/02/26/70737.aspx</guid>
            <pubDate>Sun, 26 Feb 2006 06:57:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/70737.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/02/26/70737.aspx#feedback</comments>
            <slash:comments>16</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/70737.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/70737.aspx</trackback:ping>
        </item>
        <item>
            <title>CAB sample published and future plans</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/02/19/70044.aspx</link>
            <description>&lt;P&gt;The source code for SmartPetShop, my sample project for Composite UI Application Block, is now &lt;A href="http://projectdistributor.net/Projects/Project.aspx?projectId=192"&gt;available for download&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;If you want to run it, first I recommend to download and install the original &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/petshop3x.asp"&gt;PetShop.NET 3.2 from Microsoft&lt;/A&gt; , as it will setup properly the database and register COM+ services. After that you should update the connection strings in Win application's app.config with encrypted settings taken from original Web PetShop's web.config. Simply find settings like &lt;ADD KEY="SQLCONNSTRINGX" ... &gt;and copy them to app.config. Later I will try to provide my own installation scripts for this. Finally, to compile the code you would need to place CAB DLL's om the Lib folder. 
&lt;P&gt;Currently my changes concentrate only on presentation layer so I simply replaced the Web project with my own Win project. All other code remains unchanged (with kind of proves that this is indeed well architected application).&lt;/P&gt;
&lt;H3&gt;Future plans&lt;/H3&gt;
&lt;P&gt;My first goal was to create sample application that would demonstrate how CAB can be used in real-life project. But during the process I realized I can further extend this sample and try to apply some other new technologies emerging in .NET world. So here are my future plans for this project. &lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;STRONG&gt;Finish conversion to Windows Forms&lt;/STRONG&gt; 
&lt;P&gt;From the original Web PetShop there is only couple of functions left to implement (for placing orders). But looking at CAB I already covered following features: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://geekswithblogs.net/kobush/archive/2006/01/06/65129.aspx"&gt;SmartParts and Workspaces&lt;/A&gt; 
&lt;LI&gt;&lt;A href="http://geekswithblogs.net/kobush/archive/2006/01/09/65305.aspx"&gt;WorkItems &lt;/A&gt;
&lt;LI&gt;&lt;A href="http://geekswithblogs.net/kobush/archive/2006/01/13/65775.aspx"&gt;MVP and MVC patterns&lt;/A&gt; 
&lt;LI&gt;&lt;A href="http://geekswithblogs.net/kobush/archive/2006/01/24/66946.aspx"&gt;Commands and UIElements&lt;/A&gt; 
&lt;LI&gt;and &lt;A href="http://geekswithblogs.net/kobush/archive/2006/02/05/68250.aspx"&gt;Custom UIElementAdapters&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;To make it complete I still need to discuss:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://geekswithblogs.net/kobush/archive/2006/02/26/70737.aspx"&gt;WorkItem's State and StateChange events&lt;/A&gt; 
&lt;LI&gt;Services 
&lt;LI&gt;Events and background processing 
&lt;LI&gt;Modules and WorkItem extensions 
&lt;LI&gt;ObjectBuilder&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;
&lt;LI&gt;&lt;STRONG&gt;Reimplement Data Access Layer using Enterprise Library&lt;/STRONG&gt; 
&lt;P&gt;CAB is only a little brother of EntLib so I think it makes sense to show how to use them both in the same application. I'm also curious to what degree it will simplify the original code for the data access and business logic layers. I will definitely explore the Data Access AppBlock but I will also try include others like Logging, Exception Handling and Caching. Also, I should try to replace the PetShop's ConfigTool with EntLib's Configuration. At the same time I would try to deploy the database on MS SQL 2005 Express using user instance databases and embedded update scripts (seen nice articles on both recently).&lt;/P&gt;
&lt;LI&gt;&lt;STRONG&gt;Separate client code from server&lt;/STRONG&gt; 
&lt;P&gt;I called my version SmartPetShop to indicate that it will support the SmartClient architecture. There are three main characteristics of SmartClients: rich user experience, intelligent updates, and offline capabilities. If we assume that my CAB implementation provides richer experience that the previous Web based (actually it tries to mimic it closely) there are two things left to address. For installation and updates I would use ClickOnce, but there is not much to say that wasn't well known already. So last thing is to enable the application to work without connection to server. In this mode it should at least enable to browse the product catalog and place items in shopping cart. Then, when application goes on-line, user can submit orders and check status of earlier orders.&lt;/P&gt;
&lt;P&gt;Currently the application connects directly to database so the main task here would be to move the data access and business logic to separate server process. Necessity to connect these two will allow me to explore another exciting new technology, the &lt;STRONG&gt;Windows Communication Foundation&lt;/STRONG&gt; (aka Indigo). This will also test the current architecture as it seems that it should suffice to switch ServiceAgent implementations and there should be no change to UI logic.&lt;/P&gt;
&lt;LI&gt;&lt;STRONG&gt;Another type of client&lt;/STRONG&gt; 
&lt;P&gt;When I'm done with above I should have working example of SmartClient. Then I can try to implement another type of clients. There are two candidates. I'm really excited to start working with &lt;STRONG&gt;Windows Presentation Foundation&lt;/STRONG&gt; (aka Avalon), however I don't think I would have opportunity to apply it in my professional work in foreseeable future. It is more likely that I would need to refresh my skills in ASP.NET. I stopped working on Web apps almost one and a half years ago and didn't had opportunity to try out all the goodies in ASP.NET 2.0. I'm also excited about the Atlas extensions since I've done some work with AJAX technologies on my own (some really cool DHTML behaviors). &lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;So here you have it. I will try to do as much as I can of this in upcoming months. I need to learn these things anyway but if I also put myself to write about it the process is more systematic. Feel free to drop me a note if you have additional ideas or like me to explore any particular topic more closely.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Update:&lt;/STRONG&gt; I just discovered that last week Microsoft released &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/bdasamppet4.asp"&gt;.NET Pet Shop 4.0&lt;/A&gt;. What a perfect timing! I guess I need to revise my goals as some became obsolete. Most notably these guys saved me work (and pleasure) of upgrading to ASP.NET 2.0. I haven't reviewed the code yet but judging from the accompyning article most changes were made to the presentation layer (bummer!). However, it seems it would be easier to update my code base now before starting any modifications to other layers. Anyway, it's great this project is not dead and I'm sure it will be valuable source of information on building enterprise .NET 2.0 applications for everyone. &lt;/P&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=70044"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=70044" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/70044.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/02/19/70044.aspx</guid>
            <pubDate>Sun, 19 Feb 2006 10:46:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/70044.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/02/19/70044.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/70044.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/70044.aspx</trackback:ping>
        </item>
        <item>
            <title>Understanding Composite UI Application Block, Part VI</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/02/05/68250.aspx</link>
            <description>&lt;P&gt;It's been over a week since my last post on Composite UI App Block, but don't start thinking I have given up on it already. I still want to finish the PetShop sample and at the same time to cover all important parts of CAB on this blog.&lt;/P&gt;
&lt;P&gt;Last time I have covered some basics on using Commands and UI Elements and demonstrated how I implemented commands in my sample application. But as I said before, out of the box CAB only has UIElementAdapters for ToolStrips and MenuStrips. Just to get started I put all my commands on the main menu, but the original PetShop was a web app so this were all links. So it got me thinking what it takes to implement my own UIElementAdapter. For most people support for menus and toolstrip could be enough, but some of us use third-party controls or wants to invoke commands from other controls like trees, or Outlook style navigation bars. I think knowing how to extend CAB to handle such situation can be helpful.&lt;/P&gt;
&lt;P&gt;(On the other hand, I heard on ARCast that Infragistics committed to release CAB wrappers for their controls so those of you who use NetAdvantage don't need to read any further).&lt;/P&gt;
&lt;P&gt;First thing was to create the control that will display my links and fire events when one is clicked. For this I have extended the standard &lt;SPAN style="FONT-FAMILY: Courier New"&gt;LinkLabel&lt;/SPAN&gt; adding collection of my own LinkListItems. These items are similar to a menu items having Text, Enabled, and Visible properties, and a Click event. The control automatically updates itself based on these settings. Under the hood it constructs a single line from the texts of all visible items inserting bars ( | ) as separators, and it positions a LinkArea on each enabled item. Then upon receiving LinkClicked event it propagates it back to corresponding item and fires its Click event. It took ~200 lines of code but there is nothing fancy so I won't bore you with it here.&lt;/P&gt;
&lt;P&gt;Now having the control ready I need to plug it into the CAB framework. There are three additional elements that I need to provide: IUIElementAdapter, IUIElementAdapterFactory, and CommandAdapter.&lt;/P&gt;
&lt;P&gt;As explained in last post, UIElement adapter is responsible for properly showing items of given UIElement type. This interface has only two methods: Add and Remove that are called each time items are added or removed from extension site. In my case these methods simply add or remove items from the LinkList items collection:&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;class&lt;/FONT&gt;&lt;/SPAN&gt; LinkListUIAdapter : UIElementAdapter&lt;LINKLISTITEM&gt;
{
    LinkList linkList;

    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; LinkListUIAdapter(LinkList linkList)
    {
        Guard.ArgumentNotNull(linkList, &lt;SPAN class=str&gt;&lt;FONT color=#006080&gt;"linkList"&lt;/FONT&gt;&lt;/SPAN&gt;);
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;this&lt;/FONT&gt;&lt;/SPAN&gt;.linkList = linkList;
    }

    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;override&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItem Add(LinkListItem uiElement)
    {
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;if&lt;/FONT&gt;&lt;/SPAN&gt; (linkList == &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;&lt;/SPAN&gt;)
            &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;throw&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;new&lt;/FONT&gt;&lt;/SPAN&gt; InvalidOperationException();

        linkList.Items.Add(uiElement);
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;return&lt;/FONT&gt;&lt;/SPAN&gt; uiElement;
    }

    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;override&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/SPAN&gt; Remove(LinkListItem uiElement)
    {
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;if&lt;/FONT&gt;&lt;/SPAN&gt; (uiElement.Owner != &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;&lt;/SPAN&gt;)
            uiElement.Owner.Items.Remove(uiElement);
    }
}&lt;/PRE&gt;
&lt;P&gt;The role of &lt;SPAN style="FONT-FAMILY: Courier New"&gt;IUIElementAdapterFactory&lt;/SPAN&gt; is to provide appropriate UIElementAdapter instances for given UIElement's type. The &lt;SPAN style="FONT-FAMILY: Courier New"&gt;Supports&lt;/SPAN&gt; method should indicate if particular factory supports the given UI Elements type, and then &lt;SPAN style="FONT-FAMILY: Courier New"&gt;GetAdapter&lt;/SPAN&gt; methods should create adapter for that UI Element.&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;class&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItemAdapterFactory : IUIElementAdapterFactory
{
    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; IUIElementAdapter GetAdapter(&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;object&lt;/FONT&gt;&lt;/SPAN&gt; uiElement)
    {
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;if&lt;/FONT&gt;&lt;/SPAN&gt; (uiElement &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;is&lt;/FONT&gt;&lt;/SPAN&gt; LinkList)
            &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;return&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;new&lt;/FONT&gt;&lt;/SPAN&gt; LinkListUIAdapter((LinkList)uiElement);

        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;throw&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;new&lt;/FONT&gt;&lt;/SPAN&gt; ArgumentException(&lt;SPAN class=str&gt;&lt;FONT color=#006080&gt;"uiElement"&lt;/FONT&gt;&lt;/SPAN&gt;);
    }

    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;bool&lt;/FONT&gt;&lt;/SPAN&gt; Supports(&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;object&lt;/FONT&gt;&lt;/SPAN&gt; uiElement)
    {
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;return&lt;/FONT&gt;&lt;/SPAN&gt; (uiElement &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;is&lt;/FONT&gt;&lt;/SPAN&gt; LinkList);
    }
}&lt;/PRE&gt;
&lt;P&gt;If we want to be able to attach command to the UI Elements we also need to provide a CommandAdapter. It's purpose is to provide logic that is needed for UIElement to invoke a Command, and also to synchronize changes to Command with the UI Element. Luckily for me the first part is handled by the base class EventCommandAdapter, so I only had to make sure that changes to Command status will be applied to the corresponding link:&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;class&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItemCommandAdapter : EventCommandAdapter&lt;LINKLISTITEM&gt;
{
    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItemCommandAdapter()
        : &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;base&lt;/FONT&gt;&lt;/SPAN&gt;()
    { }

    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItemCommandAdapter(LinkListItem item, &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&lt;/SPAN&gt; eventName)
        : &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;base&lt;/FONT&gt;&lt;/SPAN&gt;(item, eventName)
    { }

    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;override&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/SPAN&gt; OnCommandChanged(Command command)
    {
        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;base&lt;/FONT&gt;&lt;/SPAN&gt;.OnCommandChanged(command);

        &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;foreach&lt;/FONT&gt;&lt;/SPAN&gt; (KeyValuePair&lt;LINKLISTITEM, class=kwrd List&lt;&lt;SPAN&gt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&lt;/SPAN&gt;&amp;gt;&amp;gt; pair &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;in&lt;/FONT&gt;&lt;/SPAN&gt; Invokers)
        {
            pair.Key.Enabled = (command.Status == CommandStatus.Enabled);
            pair.Key.Visible = (command.Status != CommandStatus.Unavailable);
        }
    }
}&lt;/PRE&gt;
&lt;P&gt;Having all these three pieces we can now register them in CAB. It should be done in the AfterShellCreated method of the ShellApplication class:&lt;/P&gt;&lt;PRE class=csharpcode&gt;&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;override&lt;/FONT&gt;&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;void&lt;/FONT&gt;&lt;/SPAN&gt; AfterShellCreated()
{
    &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;base&lt;/FONT&gt;&lt;/SPAN&gt;.AfterShellCreated();

    ICommandAdapterMapService mapService = 
        RootWorkItem.Services.Get&lt;ICOMMANDADAPTERMAPSERVICE&gt;();
    mapService.Register(&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;typeof&lt;/FONT&gt;&lt;/SPAN&gt;(LinkListItem), &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;typeof&lt;/FONT&gt;&lt;/SPAN&gt;(LinkListItemCommandAdapter));

    IUIElementAdapterFactoryCatalog catalog = 
        RootWorkItem.Services.Get&lt;IUIELEMENTADAPTERFACTORYCATALOG&gt;();
    catalog.RegisterFactory(&lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;new&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItemAdapterFactory());
}&lt;/PRE&gt;Finally we have all set up and we are ready to use the new UI Elements. But the best thing it was, that the only change I had to make was to replace references to &lt;SPAN style="FONT-FAMILY: Courier New"&gt;ToolStripMenuItem&lt;/SPAN&gt; with my own &lt;SPAN style="FONT-FAMILY: Courier New"&gt;LinkListItems&lt;/SPAN&gt; like this:&lt;BR&gt;&lt;PRE class=csharpcode&gt;  LinkListItem signInItem = &lt;SPAN class=kwrd&gt;&lt;FONT color=#0000ff&gt;new&lt;/FONT&gt;&lt;/SPAN&gt; LinkListItem(&lt;SPAN class=str&gt;&lt;FONT color=#006080&gt;"SIGN IN"&lt;/FONT&gt;&lt;/SPAN&gt;);
  UIExtensionSites[&lt;SPAN class=str&gt;&lt;FONT color=#006080&gt;"NavigationBar"&lt;/FONT&gt;&lt;/SPAN&gt;].Add(signInItem);
  Commands[&lt;SPAN class=str&gt;&lt;FONT color=#006080&gt;"SignIn"&lt;/FONT&gt;&lt;/SPAN&gt;].AddInvoker(signInItem, &lt;SPAN class=str&gt;&lt;FONT color=#006080&gt;"Click"&lt;/FONT&gt;&lt;/SPAN&gt;);
&lt;/PRE&gt;&lt;BR&gt;All the other code that handles commands and updates their status remains unchanged. And thats the real advantage of CAB! &lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=68250"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=68250" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/68250.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/02/05/68250.aspx</guid>
            <pubDate>Sun, 05 Feb 2006 18:54:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/68250.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/02/05/68250.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/68250.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/68250.aspx</trackback:ping>
        </item>
        <item>
            <title>Understanding Composite UI Application Block, Part V</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/01/24/66946.aspx</link>
            <description>In most applications certain user interface areas are shared among various modules. Examples are all kinds of menus, tool bars, status bars, Outlook style sidebars and others. What is common for all of them is that they serve as containers for collections items (menu items, toolbar buttons, etc.) that user can activate to trigger some actions in the application. For example, the &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Courier New"&gt;File &amp;gt; Open&lt;/SPAN&gt; menu item normally would invoke the action of opening a file. However same action could be also accessible using a toolbar button. So it is desirable that we could decouple the user interface elements from the actions that they trigger. CAB provides solution for this in the form of &lt;STRONG&gt;UIElements&lt;/STRONG&gt; and &lt;STRONG&gt;Commands&lt;/STRONG&gt;.&amp;nbsp;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;UIExtensionSites&lt;/STRONG&gt; are the shared containers that can contain your &lt;STRONG&gt;UIElements&lt;/STRONG&gt;. Out of the box CAB provides support for &lt;STRONG&gt;MenuStrips&lt;/STRONG&gt; and &lt;STRONG&gt;ToolBarStrips&lt;/STRONG&gt; but you can easily add support for other elements by implementing your own &lt;STRONG&gt;UIElementAdapter&lt;/STRONG&gt;. After you add a menu or toolbar to your SmartPart you need to register it as an &lt;STRONG&gt;extension site&lt;/STRONG&gt;, by calling the RegisterSite method on the WorkItem.UIExtensionsSites collection and providing unique identifier for that site. Usually extension sites are registered in the RootWorkItem by the developer of shell the application. Later when module developer needs to add his own items to that site he only need to create these items as usual and than call the Add method of the specific UIExtensionSite. The corresponding UIElementAdapter is responsible for properly showing items for given UIElement type. &lt;BR&gt;&lt;BR&gt;Next step is to attach &lt;STRONG&gt;Commands&lt;/STRONG&gt; to your UIElements. Commands are used to assign easily the same code to multiple UIElements. To declare command you need to create event handler that implements your action. Then you add the &lt;STRONG&gt;CommandHandler&lt;/STRONG&gt; attribute to the method declaration specifying command name. To assign Command with a UIElement you can call the &lt;STRONG&gt;AddInvoker&lt;/STRONG&gt; method on specific Commands collection passing reference to the UIElement and specifying name of its event that will trigger the action. &lt;BR&gt;
&lt;HR&gt;
All pages in the .NET PetShop sample share a common NavigationBar that contains links to following pages: Sign In, Sign Out, Edit Account, View Shopping Cart and the Search TextBox. So we can consider them as UIElements that invoke Commands in different modules. For example, SignIn command is handled in the Account module, and ViewShoppingCart is handled in the Orders module. So it would be nice if each module could register the commands it provides and the Shell doesn't need to know anything besides providing an extension site for them.&lt;BR&gt;&lt;BR&gt;Because out of the box CAB only supports UIElementAdapters for toolbars and menus for now I will implement the navigation bar in form of the main menu to see how this works. Later I can implement a custom UIElementAdapter that would closely match the web style. &lt;BR&gt;&lt;BR&gt;First I need to add a MenuStrip to the the ShellForm and make it publicly accessible. Then I can register it as UIExtensionSite by adding following line in ShellApplication's AfterShellCreated method:&lt;BR&gt;&lt;PRE&gt;  RootWorkItem.UIExtensionSites.RegisterSite("NavBar", Shell.menuStrip);&lt;/PRE&gt;Basically that is all that shell developer needs to do -- the rest belongs to module developers. So I quickly switch hats, and go to the account management module. Let's start by adding the SignIn button. In the OnRunStarted method of AccountWorkItem I add following lines:&lt;BR&gt;&lt;PRE&gt;  ToolStripMenuItem signInItem = new ToolStripMenuItem("SIGN IN");
  UIExtensionSites["NavBar"].Add(signInItem);&lt;/PRE&gt;As you can see, first I create a normal ToolStripMenuItem. But then, instead of adding it directly to a MenuStrip, I add it to the UIExtendsionSite defined earlier. Internally CAB finds the MenuStrip defined earlier in ShellForm and passes it together with the menu item to the correct UIElementAdapter with knows how to handle them both correctly. &lt;BR&gt;&lt;BR&gt;Now, when I run the application I should see my first menu item and I can add items for other two commands (SignOut and EditAccount) the same way. However, clicking all these menu items does nothing so I need to attach handlers for appropriate events on these items. I could to this the usual way by directly attaching instance method to the Click event but in CAB we should use Commands to handle such things. Following line will register the Click event of the SignIn menu item as invoker for the SignInCommand:&lt;BR&gt;&lt;PRE&gt; Commands["SignInCommand"].AddInvoker(signInItem, "Click");&lt;/PRE&gt;To handle this command I need to declare the event handler and mark it with CommandHandler attribute:&lt;BR&gt;&lt;PRE&gt;  [CommandHandler("SignInCommand")]
  public void SignInHandler(object sender, EventArgs e)
  {
    SignIn();
  }&lt;/PRE&gt;What is important is that command handlers and UI elements that invoke them doesn't need to be defined in the same class or in other way directly accessible. For example, the command could be invoked in one WorkItem and handled in another WorkItem, SmartPart or Presenter. And I guess that there can be multiple handlers as well as many invokers attached to single command but I haven't tried this yet.&lt;BR&gt;&lt;BR&gt;In many cases command's availability depends of the application's state. For example, toolbar's undo button would be disabled if user hasn't made any modifications. In my case the SignIn button should be visible only if no user has authenticated and SignOut and My Account buttons should be visible otherwise. Normally I would control this by setting the Visible property on MenuItems but again in CAB I can do this indirectly using Commands. This ensures that if there are multiple UIElements for the same Command then all of them would get updated accordingly. Commands define the Status property that can have one of three values: Enabled, Disabled and Unavailable. When value of this property changes, the adapters linked to particular command can apply these changes to the corresponding UIElements. So in my case when user signs in or signs out I execute following code:&lt;BR&gt;&lt;PRE&gt;  if (userAuthenticated) 
    Commands["CommandSignIn"].Status = CommandStatus.Unavailable; 
  else
    Commands["CommandSignIn"].Status = CommandStatus.Enabled;&lt;/PRE&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=66946"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=66946" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/66946.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/01/24/66946.aspx</guid>
            <pubDate>Tue, 24 Jan 2006 17:28:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/66946.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/01/24/66946.aspx#feedback</comments>
            <slash:comments>13</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/66946.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/66946.aspx</trackback:ping>
        </item>
        <item>
            <title>Unit-testing in CAB applications</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/01/13/65807.aspx</link>
            <description>&lt;P&gt;Here is another gem from the message boards (thanks to Justin Burtch):&lt;/P&gt;
&lt;P&gt;One of the advantages of MVP is that it allows easier unit-testing.&amp;nbsp;For this you need to declare all public methods of view&amp;nbsp;that the presenter uses as an interface, and then you can easily substitute the actual view with its mock implementation. But to test all your components properly you need to run them in the same environment as when you run it in a GUI. By this I mean that you have some WorkItem that adds these items into the ManagedObjectCollections of the WorkItem.&amp;nbsp;The WorkItem internally uses the ObjectBuilder to create the objects and initialize the properties as specified in the attributes that adorn the properties.&lt;/P&gt;
&lt;P&gt;In the VSTS Test project for CAB, there is an object called &lt;STRONG&gt;TestableRootWorkItem&lt;/STRONG&gt;.&amp;nbsp;Create one of those and then add the view and controller into it's Items collection.&amp;nbsp;That will get the ServiceDependency to be detected and initialized.&amp;nbsp;Though the initialization you are doing by adding this WorkItem into the mix means that you're testing the CAB dependency injection framework and without a little manipulation of configuration of services, you are also testing your service.&amp;nbsp;Just means that if the test breaks, you have a couple of classes you have to investigate. &lt;/P&gt;
&lt;P&gt;Here is one example of such test from the SC-BAT project:&lt;/P&gt;&lt;PRE class=csharpcode&gt;[TestMethod]  
&lt;SPAN class=kwrd&gt;public&lt;/SPAN&gt; &lt;SPAN class=kwrd&gt;void&lt;/SPAN&gt; ShowAppraisalCalledInResponseToEventBrokerEvent()
{
   TestableRootWorkItem wi = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; TestableRootWorkItem();
   wi.Services.AddNew();
   AppraisalDetailPresenter presenter = wi.Items.AddNew();
   MockView view = &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; MockView();
   presenter.View = view;
   wi.EventTopics[Constants.EventTopics.WorkingAppraisalSelected]
     .Fire(&lt;SPAN class=kwrd&gt;this&lt;/SPAN&gt;, &lt;SPAN class=kwrd&gt;new&lt;/SPAN&gt; DataEventArgs(&lt;SPAN class=str&gt;"1"&lt;/SPAN&gt;), wi, PublicationScope.Global);
   Assert.IsTrue( view.ShowAppraisalWasCalled);
}
&lt;/PRE&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=65807"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=65807" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/65807.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/01/13/65807.aspx</guid>
            <pubDate>Fri, 13 Jan 2006 19:54:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/65807.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/01/13/65807.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/65807.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/65807.aspx</trackback:ping>
        </item>
        <item>
            <title>Understanding Composite UI Application Block, Part IV</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/01/13/65775.aspx</link>
            <description>&lt;P&gt;Yesterday I was reading &lt;A href="http://www.gotdotnet.com/codegallery/messageboard/messageboards.aspx?id=22f72167-af95-44ce-a6ca-f2eafbf2653c"&gt;CAB message boards&lt;/A&gt; and came across number of threads with questions about implementing MVP patter in CAB. Indeed, among provided samples only the walk-through uses MVP but its rather simplistic. Luckily some of these questions got answered.&lt;/P&gt;
&lt;P&gt;First of all I've learned of the &lt;A href="http://www.gotdotnet.com/codegallery/codegallery.aspx?id=941d2228-3bb5-42fd-8004-c08595821170"&gt;Smart Client Baseline Architecture Toolkit&lt;/A&gt; project, that aims to provide collection of guidance for implementing Smart Clients (including Hands-On-Labs, How-Tos and Reference Applications). Although the project just started there are already first deliverables (and they promise to release frequently on weekly base). What's important, the provided reference application show MVP in more complex scenario. It also confirms my feelings that there was something wrong in my implementation.&lt;/P&gt;
&lt;P&gt;If you want to learn about MVP pattern itself, see &lt;A href="http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf"&gt;The Humble Dialog Box&lt;/A&gt; paper, that was mentioned as one that best describes the style of MVP that Smart Client team is doing. Another great paper is &lt;A href="http://www.object-arts.com/Papers/TwistingTheTriad.PDF"&gt;Twisting The Triad: The evolution of the Dolphin Smalltalk MVP application framework&lt;/A&gt;. It starts with widget-based approach, then introduces MVC and finally explains MVP and shows how it simplifies design while leveraging strengths of both earlier patterns. You can also read the &lt;A href="http://www.martinfowler.com/eaaDev/ModelViewPresenter.html"&gt;MVP paper from Martin Fowler&lt;/A&gt; (although I read it a year ago and till now I didn't had a clue how to implement it properly).&lt;/P&gt;
&lt;P&gt;Here is how I understand Model-View-Presenter pattern right now (you can refer to the diagram from last post):&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;The Model&lt;/EM&gt; &lt;BR&gt;This is the data upon interface will operate. It is typically a domain object and there is intention that such objects should have no direct knowledge of user interface. Instead the Observer pattern (in other words events) is used to communicate changes in model to the view.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;The View&lt;BR&gt;&lt;/EM&gt;This is the presentation part that is responsible to display the contents of a model. The model is expected to trigger change notifications whenever its data is modified and these allow the view to reflect these changes on screen. This allows multiple views to be connected to a single model. &lt;/P&gt;
&lt;P&gt;The view is also responsible for handling all raw user interface events generated by user gestures. These events are then translated into operations meaningful for given view and in most cases routed to the presenter.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;The Presenter&lt;/EM&gt;&lt;BR&gt;This component governs how the model can be manipulated and changed by the user interface. Most of the user interface logic is built into a presenter class. The main difference between presenters and controllers is that presenter is &lt;EM&gt;directly &lt;/EM&gt;linked to its associated view. That means the view can pass user interface events to presenter but also presenter can directly affect the state of the view.&lt;/P&gt;
&lt;P&gt;How does it all fit in CAB? First of all you should remember that the WorkItem is NOT the model. State in WorkItam can be used to store model objects, but WorkItem is a higher level concept used to group components working together to fulfill some use case.&lt;/P&gt;
&lt;P&gt;As far as I know there is no base class for Presenter. But in summary for Controller class you can read that it is &amp;#8220;A base class for controllers and presenters that provides access to the WorkItem and State&amp;#8220;. So the only thing that is missing is reference to owning View and we can create Presenter by extending this class. I also decided to declare it with generic parameters of ViewType and WorkItemType to avoid much repetitive code.&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Presenter&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;VIEWTYPE, WorkItemType&gt; : &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Controller&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;where&lt;/FONT&gt;&lt;FONT size=2&gt; WorkItemType : &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;WorkItem&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  private&lt;/FONT&gt;&lt;FONT size=2&gt; ViewType _view;&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  &lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;  public&lt;/FONT&gt;&lt;FONT size=2&gt; ViewType View&lt;/P&gt;&lt;P&gt;  {&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; _view; }&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    set&lt;/FONT&gt;&lt;FONT size=2&gt; { _view = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;FONT size=2&gt;; }&lt;/P&gt;&lt;P&gt;  }&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/FONT&gt; &lt;/P&gt;&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;  public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; WorkItemType WorkItem&lt;/P&gt;&lt;P&gt;  {&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;base&lt;/FONT&gt;&lt;FONT size=2&gt;.WorkItem &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; WorkItemType; }&lt;/P&gt;&lt;P&gt;  }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Then I use following code to instantiate the presenter when the view is created: &lt;PRE&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;MyPresenter&lt;/FONT&gt;&lt;FONT size=2&gt; _presenter;&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;[&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CreateNew&lt;/FONT&gt;&lt;FONT size=2&gt;]&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;MyPresenter&lt;/FONT&gt;&lt;FONT size=2&gt; Presenter&lt;/P&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; _presenter; }&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  set&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;P&gt;  {&lt;/P&gt;&lt;P&gt;    _presenter = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;&lt;P&gt;    _presenter.View = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;/P&gt;&lt;P&gt;  }&lt;/P&gt;&lt;P&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/PRE&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=65775"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=65775" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/65775.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/01/13/65775.aspx</guid>
            <pubDate>Fri, 13 Jan 2006 14:45:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/65775.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/01/13/65775.aspx#feedback</comments>
            <slash:comments>4</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/65775.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/65775.aspx</trackback:ping>
        </item>
        <item>
            <title>Understanding Composite UI Application Block, Part III</title>
            <link>http://geekswithblogs.net/kobush/archive/2006/01/09/65305.aspx</link>
            <description>&lt;P&gt;Next important part of Composite UI, if not the most significant, is the &lt;STRONG&gt;WorkItem&lt;/STRONG&gt;. According to documentation it &amp;#8220;a run-time container for components that are working together to fulfill a use case. These components may consist of &lt;B&gt;SmartParts&lt;/B&gt;, controllers, services, &lt;B&gt;UIElements&lt;/B&gt;, and other components.&amp;#8221; So if we look at Outlook as example here, we have use cases like: browsing email, scheduling appointments or looking up contacts. As I understand, these would correspond to main WorkItems of EmailWorkItem, CalendarWorkItem and ContactWorkItem. Of course each of them can have child WorkItems like ComposeEmailWorkItem or EditContactWorkItem. What's more there can be also some cross references like you can call &amp;#8220;add contact&amp;#8221; use case from &amp;#8220;browse emails&amp;#8221;. &lt;/P&gt;
&lt;P&gt;What is important here is that WorkItem is the only component that has access to all other components mentioned above. Visibility of all other elements to one another is limited and basically all communication goes through the WorkItem. This architecture nicely supports two most common design patterns for moder UI: &lt;A href="http://patternshare.org/default.aspx/Home.PP.ModelViewController"&gt;Model-View-Controller&lt;/A&gt; (MVC) and &lt;A href="http://www.martinfowler.com/eaaDev/ModelViewPresenter.html"&gt;Model-View-Presenter&lt;/A&gt; (MVP). The purpose of both patterns is to separate the user interface logic from the business logic. The primary difference between them is that MVC requires events that are exposed from the model to update the view, whereas MVP depends on the presenter to update the view directly. Diagram below compares the two patterns. &lt;/P&gt;
&lt;CENTER&gt;&lt;IMG alt="Model-View-Controller vs. Model-View-Presenter" src="/images/geekswithblogs_net/kobush/1591/o_mvc_vs_mvp.jpg"&gt; &lt;/CENTER&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Here Forms, SmartParts and user controls play the role of View, and WorkItems hold state and other data that form the Model. To implement the &lt;STRONG&gt;Controller&lt;/STRONG&gt; we can derive from the base class with the same name that contains references to owning WorkItem and associated State.  
&lt;P&gt;
&lt;HR id=null&gt;

&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Lets get back to the PetShop sample and try to discover what WorkItems exist here. I would try to group the pages (now SmartParts) into following three functional areas: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Inventory &lt;/STRONG&gt;- Category, Items, ItemDetails, Search,  
&lt;LI&gt;&lt;STRONG&gt;Account - &lt;/STRONG&gt;EditAccount, CreateAccount, SignIn, SignOut, 
&lt;LI&gt;&lt;STRONG&gt;Order &lt;/STRONG&gt;- ShoppingCart, Checkout, OrderBilling, OrderProcess, OrderShipping.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I will start with the &lt;FONT face="Courier New"&gt;InventoryWorkItem&lt;/FONT&gt; because it is first thing we would probably use in the PetShop. The Category, Items and ItemDetails views are all similar - they just show bunch of data for given identifier. For first two I would use &lt;FONT face="Courier New"&gt;DataGridView&lt;/FONT&gt; and a &lt;FONT face="Courier New"&gt;BindingSource&lt;/FONT&gt; and on the last one will just throw some labels. The interesting part is how to assign the identifier to the corresponding view. For this I would implement methods in &lt;FONT face="Courier New"&gt;InventoryWorkItem&lt;/FONT&gt; that create the view, put it into the workspace and order it to load data for given identifier. Here is one such method:&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; ShowCategory(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; categoryId)&lt;/P&gt;&lt;P&gt;{ &lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;  CategoryView&lt;/FONT&gt;&lt;FONT size=2&gt; categoryView = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.SmartParts.AddNew&lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CategoryView&lt;/FONT&gt;&lt;FONT size=2&gt;&gt;();&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  this&lt;/FONT&gt;&lt;FONT size=2&gt;.Workspaces[&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"content"&lt;/FONT&gt;&lt;FONT size=2&gt;].Show(categoryView);&lt;/P&gt;&lt;P&gt;  categoryView.LoadData(categoryId);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;
&lt;P&gt;Methods &lt;FONT face="Courier New"&gt;ShowProduct&lt;/FONT&gt; and &lt;FONT face="Courier New"&gt;ShowItemDetails&lt;/FONT&gt; are implemented in similar way. But who would call these methods? Looking at the Inventory use case we have a scenario that selecting a product in a category would open a list of items for that product and then selecting one such item would show its details. Therefore I would turn one of the grid columns on both views into links and add handlers for CellContentClick event. But how do I access the WorkItem from the view? From the above diagrams I see that for this I should create a &lt;STRONG&gt;Controller&lt;/STRONG&gt;. For now it would simply forward my calls to the &lt;FONT face="Courier New"&gt;InventoryWorkItem&lt;/FONT&gt;.&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;class&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;InventoryController&lt;/FONT&gt;&lt;FONT size=2&gt; : &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;Controller&lt;/P&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;InventoryWorkItem&lt;/FONT&gt;&lt;FONT size=2&gt; WorkItem&lt;/P&gt;&lt;P&gt;  {&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;base&lt;/FONT&gt;&lt;FONT size=2&gt;.WorkItem &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;as&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;InventoryWorkItem&lt;/FONT&gt;&lt;FONT size=2&gt;; }&lt;/P&gt;&lt;P&gt;  }&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  &lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;  public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; ShowProduct(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; productId)&lt;/P&gt;&lt;P&gt;  {&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    this&lt;/FONT&gt;&lt;FONT size=2&gt;.WorkItem.ShowProduct(productId);&lt;/P&gt;&lt;P&gt;  }&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  &lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;  public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; ShowItemDetails(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; itemId)&lt;/P&gt;&lt;P&gt;  {&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;    this&lt;/FONT&gt;&lt;FONT size=2&gt;.WorkItem.ShowItemDetails(itemId);&lt;/P&gt;&lt;P&gt;  }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Now I only need to create instance of this Controller for each view. We can do it quite easily with the power of dependency injection:&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;private&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;InventoryController&lt;/FONT&gt;&lt;FONT size=2&gt; _inventoryController;&lt;/P&gt;&lt;P&gt; &lt;/P&gt;&lt;P&gt;[&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CreateNew&lt;/FONT&gt;&lt;FONT size=2&gt;]&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;InventoryController&lt;/FONT&gt;&lt;FONT size=2&gt; InventoryController&lt;/P&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  get&lt;/FONT&gt;&lt;FONT size=2&gt; { &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT size=2&gt; _inventoryController; }&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;  set&lt;/FONT&gt;&lt;FONT size=2&gt; { _inventoryController = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;value&lt;/FONT&gt;&lt;FONT size=2&gt;; }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;The &lt;FONT face="Courier New"&gt;CreateNew&lt;/FONT&gt; attribute instructs the ObjectBuilder to instantiate and initialize the &lt;FONT face="Courier New"&gt;InventoryController&lt;/FONT&gt; when the SmartPart is created. How convenient.&lt;/P&gt;
&lt;P&gt;One last thing is to actually create and Run the InventoryWork item. I would do this whenever user selects one of the categories from the default page or the navigation bar. And now I realize that I also need a root WorkItem to maintain the main page and other WorkItems. I create a ShellWorkItem and change the declaration of ShellApplication class. Now I can also move the code that loads the default page from application's AfterShellCreated to ShellWorkItem's OnRunStarted method. Finally, here is the code to run the InventoryWorkItem when user selects a category:&lt;/P&gt;&lt;PRE&gt;&lt;FONT size=2&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;public&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT size=2&gt; ShowCategory(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; categoryId)&lt;/P&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;  InventoryWorkItem&lt;/FONT&gt;&lt;FONT size=2&gt; inventory = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;this&lt;/FONT&gt;&lt;FONT size=2&gt;.WorkItems.AddNew&lt;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;InventoryWorkItem&lt;/FONT&gt;&lt;FONT size=2&gt;&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"inventory"&lt;/FONT&gt;&lt;FONT size=2&gt;);&lt;/P&gt;&lt;P&gt;  inventory.Run();&lt;/P&gt;&lt;P&gt;  inventory.ShowCategory(categoryId);&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;/PRE&gt;
&lt;P&gt;Ok. Now I will try to implement remaining views using what I've learned already. I won't be boring you with details until I start to use some new elements. &lt;/P&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=65305"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=65305" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/kobush/aggbug/65305.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Szymon Kobalczyk</dc:creator>
            <guid>http://geekswithblogs.net/kobush/archive/2006/01/09/65305.aspx</guid>
            <pubDate>Mon, 09 Jan 2006 05:40:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/kobush/comments/65305.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/kobush/archive/2006/01/09/65305.aspx#feedback</comments>
            <slash:comments>14</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/kobush/comments/commentRss/65305.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/kobush/services/trackbacks/65305.aspx</trackback:ping>
        </item>
    </channel>
</rss>