<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6088992123466333517</id><updated>2011-11-27T18:39:24.124-05:00</updated><category term='thin client'/><category term='domain model'/><category term='Converting SketchFlow to Production'/><category term='2D drawing'/><category term='asynchronous'/><category term='SQL Server'/><category term='lists'/><category term='Virtual Earth'/><category term='visibility'/><category term='Expression Blend'/><category term='serialization'/><category term='OOB'/><category term='SOA'/><category term='VisualStateManager'/><category term='rendertransform'/><category term='drag and drop'/><category term='XAML'/><category term='grid'/><category term='Generic Conversion'/><category term='zoom'/><category term='mouse move'/><category term='mouse wheel'/><category term='SketchFlow'/><category term='canvas'/><category term='synchronous'/><category term='trigonometry'/><category term='View Model'/><category term='Silverlight 3'/><category term='hit testing'/><category term='LINQ'/><category term='loops'/><category term='Best Buy'/><category term='visual tree'/><category term='Silverlight 4'/><category term='RIA Services'/><category term='element binding'/><category term='thick client'/><category term='visio'/><category term='stackpanel'/><category term='opacity'/><category term='custom panel'/><category term='data abstraction'/><category term='WCF'/><category term='PDC'/><category term='Bing Maps'/><category term='MediaElement'/><category term='data storage'/><category term='IValueConverter'/><category term='VS2010'/><category term='directory name is invalid'/><category term='rich client'/><category term='Expression Blend 3'/><category term='data services'/><category term='architecture'/><category term='Tips and Tricks'/><category term='Silverlight'/><category term='.NET'/><category term='binding'/><title type='text'>Silver Enlightenment</title><subtitle type='html'>What We've Learned While Building Silverlight Applications...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3458204044084354453</id><published>2010-04-14T23:38:00.006-04:00</published><updated>2010-07-26T13:12:54.023-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><category scheme='http://www.blogger.com/atom/ns#' term='Tips and Tricks'/><title type='text'>Generic Property Merge Using Reflection</title><content type='html'>&lt;p&gt;I have found this generic merge method to be very useful.  Before you cut and paste it into you Silverlight application, let me explain why I created it.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:14da9b9d-fe57-4ea5-a375-8b7bb8dcac82" class="wlWriterEditableSmartContent"&gt;&lt;div style="BORDER-BOTTOM: #000080 1px solid; BORDER-LEFT: #000080 1px solid; BORDER-TOP: #000080 1px solid; BORDER-RIGHT: #000080 1px solidfont-family:'Courier New', Courier, Monospace;font-size:10pt;color:#000;"   &gt;&lt;div style="BACKGROUND: #fff; MAX-HEIGHT: 300px; OVERFLOW: auto"&gt;&lt;ol style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 5px; PADDING-RIGHT: 0px; WHITE-SPACE: nowrap; BACKGROUND: #ffffff; PADDING-TOP: 0px"&gt;&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; MergeValues(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; oSource, &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; bNotifyUI)&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;{&lt;/li&gt;&lt;li&gt;    &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; bSucess = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;&lt;/li&gt;&lt;li&gt;    &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; oPropInfo &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; oSource.GetType().GetProperties())&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    {&lt;/li&gt;&lt;li&gt;        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (!oPropInfo.CanRead  !oPropInfo.CanWrite  oPropInfo.Name == &lt;span style="color:#a31515;"&gt;"Item"&lt;/span&gt;)&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;            &lt;span style="color:#0000ff;"&gt;continue&lt;/span&gt;;&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;        &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; oResult = oPropInfo.GetValue(oSource, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);&lt;/li&gt;&lt;li&gt;        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (oResult != oPropInfo.GetValue(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;))&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;            &lt;span style="color:#0000ff;"&gt;try&lt;/span&gt;&lt;/li&gt;&lt;li&gt;            {&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;                oPropInfo.SetValue(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, oResult, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);&lt;/li&gt;&lt;li&gt;                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (bNotifyUI)&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;                    NotifyOfPropertyChange(oPropInfo.Name);&lt;/li&gt;&lt;li&gt;            }&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;            &lt;span style="color:#0000ff;"&gt;catch&lt;/span&gt;&lt;/li&gt;&lt;li&gt;            {&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;                bSucess = &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;;&lt;/li&gt;&lt;li&gt;            }&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    }&lt;/li&gt;&lt;li&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; bSucess;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;}&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Once Silverlight binds a property to a XAML element, your program will perform a lot better if you just change the value rather then rebind to a new object.  I have not done any detailed timing tests, but by using this code in a before / after way you can “feel” that this is faster.  &lt;/p&gt;&lt;p&gt;I know there is a performance cost when you access a property via reflection, but I am willing to pay that cost to have a solution that is VERY reliable.&lt;/p&gt;&lt;p&gt;By defining this method as &lt;strong&gt;virtual&lt;/strong&gt; you are able to &lt;strong&gt;override&lt;/strong&gt; to build a version that performs better, for example:&lt;/p&gt;&lt;div style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; DISPLAY: inline; FLOAT: none; PADDING-TOP: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:1a3e4977-67c2-4cf0-a4cb-47da05d07733" class="wlWriterEditableSmartContent"&gt;&lt;div style="BORDER-BOTTOM: #000080 1px solid; BORDER-LEFT: #000080 1px solid; BORDER-TOP: #000080 1px solid; BORDER-RIGHT: #000080 1px solidfont-family:'Courier New', Courier, Monospace;font-size:10pt;color:#000;"   &gt;&lt;div style="BACKGROUND: #fff; MAX-HEIGHT: 300px; OVERFLOW: auto"&gt;&lt;ol style="PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 5px; PADDING-RIGHT: 0px; WHITE-SPACE: nowrap; BACKGROUND: #ffffff; PADDING-TOP: 0px"&gt;&lt;li&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; MergeValues(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; oSource, &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; bNotifyUI)&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;{&lt;/li&gt;&lt;li&gt;    &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; bSucess = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    Person oPerson = oSource &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; Person;&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ID = oPerson.ID;&lt;/li&gt;&lt;li&gt;    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.FirstName = oPerson.FirstName;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.MiddleName = oPerson.MiddleName;&lt;/li&gt;&lt;li&gt;    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.LastName = oPerson.LastName;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.MostRecentFlight = oPerson.MostRecentFlight;&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;li style="BACKGROUND: #f3f3f3"&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; bSucess;&lt;/li&gt;&lt;li&gt;}&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;But this solution is not as reliable and requires me to change the code every time I modify the properties in this class.&lt;/p&gt;&lt;p&gt;Feel free to cut, paste and modify this code to meet your own coding objectives.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3458204044084354453?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3458204044084354453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3458204044084354453&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3458204044084354453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3458204044084354453'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/04/generic-property-merge-using-reflection.html' title='Generic Property Merge Using Reflection'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3798252512480953927</id><published>2010-03-21T11:57:00.005-04:00</published><updated>2010-07-26T13:20:06.646-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><title type='text'>NCAA Brackets in Silverlight</title><content type='html'>The developers at a company we were working with put out a challenge -- can you write software to pick the brackets in the NCAA basketball tournament? The answer is you can and 6 of us did. Our solutions range from random number generators to multivariate stepwise regressions. We did the multivariate stepwise regression.&lt;br /&gt;&lt;br /&gt;I created a Silverlight application to display the results; that is, Debra designed the application and I did the software.  The code is posted to codeplex &lt;a href="http://ncaabasketball.codeplex.com/"&gt;here&lt;/a&gt;, and you can see our picks at &lt;a href="http://www.mysilverisland.com/NCAA"&gt;http://www.mysilverisland.com/NCAA&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The code is very object oriented and uses a direct approach to pushing the data into the view.  No MV-VM was necessary, but that was because of the nature of the solution.  This application simply creates a report of our picks, and the picks are shoved into the brackets using a "plug and chug" technique of matching textbox names with ID's in a collection.&lt;br /&gt;&lt;br /&gt;I think this code may be useful for other developers who need to manage a tournament.&lt;br /&gt;&lt;br /&gt;You can get the source code on codeplex:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ncaabasketball.codeplex.com/"&gt;http://ncaabasketball.codeplex.com/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3798252512480953927?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3798252512480953927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3798252512480953927&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3798252512480953927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3798252512480953927'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/03/ncaa-brackets-in-silverlight.html' title='NCAA Brackets in Silverlight'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-8516671562298019236</id><published>2010-02-25T21:56:00.002-05:00</published><updated>2010-07-16T22:25:17.596-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips and Tricks'/><title type='text'>Another Way to Think about Code Reuse</title><content type='html'>&lt;p&gt;Anyone who practices Object Oriented Programming has a lot of different ways to reuse code. The most common way is to use inheritance, but recently I have been reusing code in an unconventional way. &lt;/p&gt;  &lt;p&gt;Whenever I create a class I follow a strict convention on naming properties. Here is an example: &lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:d73a52ab-60a4-49a6-8d7a-f3bdec73b029" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #fff; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Movie&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; Title { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; List&amp;lt;People&amp;gt; Actors { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af"&gt;DateTime&lt;/span&gt; ReleaseDate { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;double&lt;/span&gt; MoneyEarnedToDate { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; Producer { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; Genre { &lt;span style="color:#0000ff"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff"&gt;set&lt;/span&gt;; }&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;br /&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/CamelCase" target="_blank"&gt;CamelCase&lt;/a&gt; is the convention I use to define every property. I always use complete words and never use abbreviations. I do not use underscores in public properties. I stick to this convention because it lets me extract Meta data from the class while it is in use and can be used to simplify coding of the UI. &lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:d1df70ab-8ecc-4e0e-a839-18783ce8a93f" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #fff; max-height: 500px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px;"&gt; &lt;li&gt;&lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af"&gt;CustomGrid&lt;/span&gt; : &lt;span style="color:#2b91af"&gt;DataGrid&lt;/span&gt; &lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;{&lt;/li&gt; &lt;li&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; CustomGrid()&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        : &lt;span style="color:#0000ff"&gt;base&lt;/span&gt;()&lt;/li&gt; &lt;li&gt;    {&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        AutoGenerateColumns = &lt;span style="color:#0000ff"&gt;true&lt;/span&gt;;&lt;/li&gt; &lt;li&gt;        AutoGeneratingColumn += &lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af"&gt;DataGridAutoGeneratingColumnEventArgs&lt;/span&gt;&amp;gt;(OnAutoGeneratingColumn);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    }&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; OnAutoGeneratingColumn(&lt;span style="color:#0000ff"&gt;object&lt;/span&gt; sender, &lt;span style="color:#2b91af"&gt;DataGridAutoGeneratingColumnEventArgs&lt;/span&gt; e)&lt;/li&gt; &lt;li&gt;    {&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; sHeader = e.Column.Header.ToString();&lt;/li&gt; &lt;li&gt;        e.Column.Header = CamelToTitleCase(sHeader);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    }&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;string&lt;/span&gt; CamelToTitleCase(&lt;span style="color:#0000ff"&gt;string&lt;/span&gt; Text)&lt;/li&gt; &lt;li&gt;    {&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        Text = Text.Substring(0, 1).ToUpper() + Text.Substring(1);&lt;/li&gt; &lt;li&gt;        &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Regex&lt;/span&gt;.Replace(Text, &lt;span style="color:#a31515"&gt;@&amp;quot;(&amp;#92;B[A-Z])&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515"&gt;@&amp;quot; $1&amp;quot;&lt;/span&gt;);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;    }&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;br /&gt;  &lt;p&gt;Via inheritance I can customize the standard Silverlight DataGrid to automatically generate columns for whatever class is bound to it. I sign up for the OnAutoGeneratingColumn event so I can rename the column headings. The function CamelToTitleCase will automatically insert spaces before each capitol letter, so the property &lt;em&gt;ReleaseDate &lt;/em&gt;becomes the header &lt;em&gt;Release Date&lt;/em&gt; and the property &lt;em&gt;MoneyEarnedToDate&lt;/em&gt; becomes &lt;em&gt;Money Earned To Date&lt;/em&gt;&lt;/p&gt; &lt;a href="http://4.bp.blogspot.com/_x0fXcQg3teU/TEA1oAkJ0-I/AAAAAAAAACo/pEdYGSNETU8/s1600/CustomGridTitle.png"&gt;&lt;img style="width: 660px; height: 68px; cursor: hand" id="BLOGGER_PHOTO_ID_5494450506854683618" border="0" alt="" src="http://4.bp.blogspot.com/_x0fXcQg3teU/TEA1oAkJ0-I/AAAAAAAAACo/pEdYGSNETU8/s400/CustomGridTitle.png" /&gt;&lt;/a&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;p&gt;So is using a coding convention really code reuse or is it more like asset repurposing? I have learned that having a convention makes my code easier to read and debug. It also leads to even more advanced techniques I will share in later blogs. &lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-8516671562298019236?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/8516671562298019236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=8516671562298019236&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8516671562298019236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8516671562298019236'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/02/another-way-to-think-about-code-reuse.html' title='Another Way to Think about Code Reuse'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_x0fXcQg3teU/TEA1oAkJ0-I/AAAAAAAAACo/pEdYGSNETU8/s72-c/CustomGridTitle.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3592167648216808784</id><published>2010-02-15T05:32:00.005-05:00</published><updated>2010-07-15T19:16:12.770-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Know Your Parents and Grandparents</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;In programming Silverlight I have come across situations where a control or framework element needs to access information on its parent. The code to get information off your direct parent is simple:&lt;/p&gt;  &lt;br /&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:f2e09aed-3bce-435c-ba15-85d0c8ffd4d1" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #fff; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"&gt; &lt;li&gt;            &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; oContent = &lt;span style="color:#0000ff"&gt;this&lt;/span&gt;.Parent.ReadLocalValue(Content);&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; for example.  &lt;br /&gt;  &lt;p&gt;The real power of Silverlight is in the declarative nesting of XAML elements, and that means that the type of your direct parent may not always be known. To clarify, if you drop a control on a Page, then the Page object will be your parent. However if you then wrap your control in a ScrollViewer, the ScrollViewer becomes your parent and the Page becomes your grandparent. &lt;/p&gt;  &lt;p&gt;To avoid all these issues I include the following code in most of my Silverlight projects:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:905ab6ef-993a-4af3-89eb-712e2921882f" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #fff; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"&gt; &lt;li&gt;        &lt;span style="color:#0000ff"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff"&gt;virtual&lt;/span&gt; T ParentOfType&amp;lt;T&amp;gt;() &lt;span style="color:#0000ff"&gt;where&lt;/span&gt; T : &lt;span style="color:#2b91af"&gt;FrameworkElement&lt;/span&gt;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        {&lt;/li&gt; &lt;li&gt;            &lt;span style="color:#2b91af"&gt;Type&lt;/span&gt; oType = &lt;span style="color:#0000ff"&gt;typeof&lt;/span&gt;(T);&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;            &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; oParent = Parent &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af"&gt;FrameworkElement&lt;/span&gt;;&lt;/li&gt; &lt;li&gt;            &lt;span style="color:#0000ff"&gt;while&lt;/span&gt; (oParent != &lt;span style="color:#0000ff"&gt;null&lt;/span&gt;)&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;            {&lt;/li&gt; &lt;li&gt;                &lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (oType.IsInstanceOfType(oParent))&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;                    &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; oParent &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; T;&lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;                &lt;span style="color:#0000ff"&gt;if&lt;/span&gt; (oParent.GetType() == oType)&lt;/li&gt; &lt;li&gt;                    &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; oParent &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; T;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt;                oParent = oParent.Parent &lt;span style="color:#0000ff"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af"&gt;FrameworkElement&lt;/span&gt;;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;            }&lt;/li&gt; &lt;li&gt;            &lt;span style="color:#0000ff"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff"&gt;null&lt;/span&gt;;&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        }&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;br /&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Recently I needed to access the Navigation Service that is part of a Silverlight Page object. Using the method above I wrote this code to access the service:   &lt;br /&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:e5178b0b-b5cb-4d0b-b6d1-6b1df535d796" class="wlWriterEditableSmartContent"&gt; &lt;div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"&gt; &lt;div style="background: #fff; max-height: 300px; overflow: auto"&gt; &lt;ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"&gt; &lt;li&gt;        &lt;span style="color:#0000ff"&gt;void&lt;/span&gt; OnMouseLeftButtonDown(&lt;span style="color:#0000ff"&gt;object&lt;/span&gt; sender, &lt;span style="color:#2b91af"&gt;MouseButtonEventArgs&lt;/span&gt; e)&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        {&lt;/li&gt; &lt;li&gt;            &lt;span style="color:#0000ff"&gt;var&lt;/span&gt; oPage = ParentOfType&amp;lt;&lt;span style="color:#2b91af"&gt;Page&lt;/span&gt;&amp;gt;();&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;&amp;nbsp;&lt;/li&gt; &lt;li&gt; &lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;            &lt;span style="color:#0000ff"&gt;if&lt;/span&gt; ( oPage != &lt;span style="color:#0000ff"&gt;null&lt;/span&gt; )&lt;/li&gt; &lt;li&gt;                oPage.NavigationService.Navigate(&lt;span style="color:#0000ff"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af"&gt;Uri&lt;/span&gt;(NavigateUri, &lt;span style="color:#2b91af"&gt;UriKind&lt;/span&gt;.RelativeOrAbsolute));&lt;/li&gt; &lt;li style="background: #f3f3f3"&gt;        }&lt;/li&gt; &lt;/ol&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt;  &lt;br /&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Now regardless where this control is placed in the XAML, the Navigation Service will execute correctly.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3592167648216808784?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3592167648216808784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3592167648216808784&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3592167648216808784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3592167648216808784'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/07/know-your-parents-and-grand-parents.html' title='Know Your Parents and Grandparents'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-981281294716100254</id><published>2010-01-25T14:14:00.001-05:00</published><updated>2010-07-10T14:29:37.876-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><title type='text'>What I Learned at PDC - Microsoft Tools</title><content type='html'>Visual Studio 2010 (VS210) is the latest version of the software development platform. It is also the first version to be written entirely in .NET managed code. It also uses MEF to manage extensibility and WPF to implement all the UI and code editing tools. Microsoft also offers a development environment for GUI and web designers call Expression Blend. Blend and VS2010 share the same project file format so projects can be shared between developers and designers easily.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDi5iCQG6vI/AAAAAAAAAN4/7hw4DGc1Ujo/s1600/Tools.jpg"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 88px; FLOAT: left; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492343739949443826" border="0" alt="" src="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDi5iCQG6vI/AAAAAAAAAN4/7hw4DGc1Ujo/s400/Tools.jpg" /&gt;&lt;/a&gt;Developers, you should know that every demo at PDC was done using VS2010 and there are lots of sessions that dive into the new features. An existing but little used VS2010 feature (that may go as far back as the very first VS) is T4 templates. These are code generation templates that developers can customize to pragmatically create code. Scott Hanselman show this technique at 20 minutes into his talk &lt;a href="http://microsoftpdc.com/Sessions/FT59"&gt;FT59: ASP.NET MVC 2: Ninjas Still on Fire Black Belt Tips&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Designers, VS2010 also includes a design surface to help developers create GUI in WPF/XAML. It works well for simple GUI composition, but is not good for real creative work. Blend is the tool of choice for creating GUI with animations or custom controls that use Virtual State Manager.&lt;br /&gt;&lt;br /&gt;For non-developers, there are only 2 things you need to know about this tool:&lt;br /&gt;&lt;br /&gt;1) VS2010 can generate code for any version of the .NET framework in existence; this feature is called multi-target deployment. Developers can port their projects to VS2010 without being forced to upgrade to a specific version of .NET. By simply flipping a compiler switch, you can retarget your application to take advantage of later versions of .NET. I have tried this on software I wrote for .NET 1.1 and it works great. It runs in .NET 3.5 and 4.0 without any issues.&lt;br /&gt;&lt;br /&gt;2) In building VS2010, Microsoft’s main focus was developer productivity. I have found that I was immediately productive with VS2010 and took advantage of many of the new features, like a visual form builder for Silverlight applications, intuitively.&lt;br /&gt;&lt;br /&gt;Bottom Line: developers should install and start working with VS 2010 right away. Simple new features, like being able to open VS2010 windows on multiple separate monitors, will improve developer productivity or at least reduce programmer fatigue. Also check out &lt;a href="http://microsoftpdc.com/Sessions/CL09"&gt;CL09: How Microsoft Visual Studio 2010 Was Built with WPF 4&lt;/a&gt; to see how Microsoft uses their own technology to build their own products. This talk also shows a tool named Snoop that lets you see all the layers of the WPF tree being rendered: &lt;a href="http://www.blois.us/Snoop/"&gt;Snoop&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Quality Assurance, Testing, Performance and Source Code Control&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;These tools make the difference between hacking out code and developing software professionally. I have an interest in all these tools but they are not my primary focus, so here is a quick list of the sessions I attended or watched and my comments.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://microsoftpdc.com/Sessions/CL25"&gt;CL25: Become a Web Debugging Virtuoso with Fiddler&lt;/a&gt;: If you are building / testing / debugging web applications, Fiddler is a tool that can let you see communication between your web browser and the server. This talks show how that and other features of Fiddler can help you create web applications.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://microsoftpdc.com/Sessions/CL32"&gt;CL32: Developing Testable Silverlight Applications&lt;/a&gt;: This talks shows, in detail, how to build automated unit tests for Silverlight applications that can mimic user interaction. It also shows how you can write applications that are more testable by using the MV-VM pattern.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://microsoftpdc.com/Sessions/FT35"&gt;FT35: Microsoft Visual C# IDE Tips and Tricks&lt;/a&gt;: Learn some productivity tips that are new in VS2010. Learn how to get a deeper insight into your code and improve your speed to solution. DJ Park proves it by racing the clock to generate code, a must-see event 43 minutes in. Also check out &lt;a href="http://msdn.microsoft.com/en-us/vcsharp/dd218053.aspx"&gt;CodeRush Xpress for C#&lt;/a&gt; . It is a free refactoring tool that lets you move around bodies of C# code while preserving the coding intent. Also check out the Architecture Explorer in VS2010, 13 minutes into the talk.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://microsoftpdc.com/Sessions/FT54"&gt;FT54: Power Tools for Debugging&lt;/a&gt;: Debugging is hard; VS2010 has some new debugging tools like Intellitrace to make it easier. But this talk is mainly about research into future debugging tools. They show a Holmes, a statistical debugger that can find a correlation between code paths and test failures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-981281294716100254?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/981281294716100254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=981281294716100254&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/981281294716100254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/981281294716100254'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/01/what-i-learned-at-pdc-microsoft-tools.html' title='What I Learned at PDC - Microsoft Tools'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_s1N_RQkyQXU/TDi5iCQG6vI/AAAAAAAAAN4/7hw4DGc1Ujo/s72-c/Tools.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2935798437270115895</id><published>2010-01-20T14:03:00.001-05:00</published><updated>2010-07-10T14:10:39.461-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><title type='text'>What I Learned at PDC - .NET Platform and Extensions (continued)</title><content type='html'>&lt;a href="http://3.bp.blogspot.com/_s1N_RQkyQXU/TDi2gKmMbwI/AAAAAAAAANw/YnJki0496yE/s1600/NETPlatform.jpg"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 117px; FLOAT: left; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492340409294941954" border="0" alt="" src="http://3.bp.blogspot.com/_s1N_RQkyQXU/TDi2gKmMbwI/AAAAAAAAANw/YnJki0496yE/s400/NETPlatform.jpg" /&gt;&lt;/a&gt;&lt;strong&gt;Composition Manager (MEF) and Construction Manager (Prism)&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The Microsoft Patterns and Practices team have built software libraries to help large teams develop large applications. It turns out that these techniques also work well in any application.&lt;br /&gt;&lt;br /&gt;MEF stands for Managed Extensibility Framework. This is a technology designed to introduce extensibility points (like Office or web browser plug-ins) into your application. Developing with extensibility in mind lets you think of your application as a platform and can simplify your other development efforts. A well componentized application can be extended after it is deployed by third parties that have special or advanced needs. The technique can foster an ecosystem around the original application, letting others open new markets for your original solution. Glenn Block has a hand in creating MEF and Prism: &lt;a href="http://microsoftpdc.com/Sessions/FT24"&gt;FT24: Building Extensible Rich Internet Applications with the Managed Extensibility Framework&lt;/a&gt; . Listen to the first 5 minutes to understand the problem MEF is solving. Projects can be extended by MEF after initial development, but it is best to think about extension points as you go. Watch the demos first, then circle back to get see how it is done. I love the demo he does 45 minutes into the talk. It shows how MEF can be used to control feature access and deliver functionality on demand. At 50 minutes in you can see a series of demos that have real world application.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Extensibility can also be a competitive advantage.&lt;/strong&gt; If you expose your application by exposing data services, you may be fostering competition from others to build their own client. Providing extensibility in your own client lets would-be competitors become partners by building extensions that use your data services client plug-ins. A step by step &lt;a href="http://channel9.msdn.com/tags/MEF/"&gt;demo on adding MEF to your application&lt;/a&gt; is done my Mike Taulty, whom I also had a chance to meet.&lt;br /&gt;Prism is not an acronym for anything -- it is a collection of technology services and constructs that promote loose coupling of software components by introducing a series of “management” object classes. Prism is not really a Microsoft product, so it does not get the marketing push, but anyone who was discussing a rich client application talked about using Prism.&lt;br /&gt;&lt;br /&gt;The best guide I have heard, hands down, on Prism is from my friend Eric Mork: &lt;a href="http://development-guides.silverbaylabs.org/"&gt;Prism Development Guides and Videos&lt;/a&gt;. If you follow this link, also sign up for his podcast where he talks technology with many of the experts in the Silverlight community. The commanding feature of Prism is now unnecessary with the addition of ICommand in Silverlight.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2935798437270115895?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2935798437270115895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2935798437270115895&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2935798437270115895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2935798437270115895'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/01/what-i-learned-at-pdc-net-platform-and_20.html' title='What I Learned at PDC - .NET Platform and Extensions (continued)'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_s1N_RQkyQXU/TDi2gKmMbwI/AAAAAAAAANw/YnJki0496yE/s72-c/NETPlatform.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-5629821195519114603</id><published>2010-01-15T13:45:00.004-05:00</published><updated>2010-07-10T14:16:54.360-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><category scheme='http://www.blogger.com/atom/ns#' term='LINQ'/><title type='text'>What I Learned at PDC - .NET Platform and Extensions</title><content type='html'>&lt;a href="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDizGvr1v8I/AAAAAAAAANo/Hmci-HM5lb8/s1600/NETPlatform.jpg"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 117px; FLOAT: left; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492336674039250882" border="0" alt="" src="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDizGvr1v8I/AAAAAAAAANo/Hmci-HM5lb8/s400/NETPlatform.jpg" /&gt;&lt;/a&gt; In the late 90’s, the general consensus was that the Microsoft programming model was losing ground to JAVA. At that time, every product that Microsoft offered was COM(Component Object Model) based. And every language Microsoft offered produced COM programs. The COM programming model generated machine instructions targeted at the native instruction set of the CPU. JAVA, on the other hand, provided a virtual machine environment, so compiled JAVA code targeted the instruction set of the virtual machine (VM), which is an abstract CPU. JAVA was able to use its VM implementation to create the catch phrase “write once, run anywhere”, because all that was needed to execute your JAVA program on any OS, platform or device was an implementation of the JAVA VM. There was no need to recompile your JAVA code in order to run it on a new target machine, and as a result there was no need to created install programs to set up the target machine. ‘X-COPY deployment’ become another catch phrase because all you needed to do to install and run a JAVA program was to copy the binaries to a folder on the target machine and say run!&lt;br /&gt;&lt;br /&gt;In early 2000 Microsoft released .NET, its own VM based programming environment. At the time, Steve Balmer described .NET as a corporate strategy, programming environment and a marketing campaign. All programming languages implemented in .NET (VB, C#, C++) would emit the same instruction set and target the VM. This makes is possible to easily create applications that mix languages. .NET also makes it possible to call into programs written in the older COM technology through a process called ‘interop’.&lt;br /&gt;&lt;br /&gt;Throughout this decade Microsoft has been improving the .NET platform. Two new technologies that emerged in .NET were WPF (Windows Presentation Foundation) and WCF (Windows Communication Foundation). These technologies are the core components used for GUI and networking.&lt;br /&gt;&lt;br /&gt;So what is new and improved in the .NET platform? Everything, starting with .NET itself.&lt;br /&gt;&lt;br /&gt;The latest version of .NET is .NET 4.0. It should be noted that many of the productivity frameworks come in the box as part of the .NET 4.0 platform, and have also been back-ported to .NET 3.0 and VS2080 SP1. Many are also open source.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Language and Modeling Tools&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;.NET Framework (POCO, LINQ, Rx, IDynamic )&lt;/strong&gt; : it all starts with improvements to the .NET framework. POCO is an acronym for Plain Old CLR Objects (CLR is Common Language Runtime), and although POCO has been around since .NET 1.0, Microsoft is favoring this type of detailed definition for data binding and transportation over the existing classes like DataSet, DataTable &amp;amp; DataRow. I think it is because they work better with LINQ (Language Integrated Query).&lt;br /&gt;&lt;br /&gt;LINQ is a fabulous technology (&lt;a href="http://en.wikipedia.org/wiki/Language_Integrated_Query"&gt;Wikipedia: Language Integrated Query&lt;/a&gt;) for lots of reasons. One of the most important, from a developer’s point of view, is that it reduces the interaction with any .NET data source (SQL, XML, CSV…) into a single syntax.&lt;br /&gt;&lt;br /&gt;Rx, or Reactive Framework, was one of the surprises of PDC, and I did not even discover it until after the conference, online. The LINQ model is to pull data from a data source, where the Rx model reacts to changes in the data source and sends you a notification. The session &lt;a href="http://microsoftpdc.com/Sessions/VTL04"&gt;VTL04: Rx: Reactive Extensions for .NET&lt;/a&gt; explains how it works. Eric Meijer leads the talk and he always wears a tie-dyed shirt, always.&lt;br /&gt;&lt;br /&gt;IDyamic is the feature / interface I have been waiting for since the PDC08 demos. Dynamic languages defer compile type checking to runtime and in many cases this is very useful. Popular languages like Ruby (on Rails) use this technique exclusively. This, in conjunction with the DLR (Dynamic Language Runtime), will make is possible to extend the syntax of any .NET language. It offers better interop with COM based software, like Office and VB6. The DLR is also a major component for languages like Iron Ruby and Iron Python. Mads Torgerson gives a solid talk on the development history: &lt;a href="http://microsoftpdc.com/Sessions/FT31"&gt;FT31: Dynamic Binding in C# 4&lt;/a&gt;. Luck Bolognese gives a talk that shows using the technology: &lt;a href="http://microsoftpdc.com/Sessions/FT11"&gt;FT11: Future Directions for C# and Visual Basic&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Adding dynamic characteristics to existing languages follows the theme of programming in a declarative style instead of an imperative style.&lt;br /&gt;&lt;br /&gt;I will finish this topic in my next post on PDC, where I will talk about MEF and Prism...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-5629821195519114603?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/5629821195519114603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=5629821195519114603&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5629821195519114603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5629821195519114603'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/01/what-i-learned-at-pdc-net-platform-and.html' title='What I Learned at PDC - .NET Platform and Extensions'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_s1N_RQkyQXU/TDizGvr1v8I/AAAAAAAAANo/Hmci-HM5lb8/s72-c/NETPlatform.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-8829176351500431700</id><published>2010-01-10T13:26:00.002-05:00</published><updated>2010-07-10T13:45:16.356-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data storage'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><category scheme='http://www.blogger.com/atom/ns#' term='data services'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 4'/><category scheme='http://www.blogger.com/atom/ns#' term='OOB'/><category scheme='http://www.blogger.com/atom/ns#' term='data abstraction'/><title type='text'>What I Learned from PDC - Server Technologies</title><content type='html'>The server is a provider of a set of services to support the client and the domain. The server is hosted on a machine that could be anywhere on the internet or on the same machine as the client. There are also a lot of applications (like Microsoft Office, video games) where the client (GUI) / server (Services) are integrated into one common executable. Think of a Server as software that is providing a set of services to many clients. Cloud computing has changed the notion that a Server as a physical machine on the internet -- that type of thinking makes it hard to grasp the ideas to come. Envision a server as a provider of a set of services -- authentication, billing, data retrieval and persistence, document management, 24/7 availability, scalability, compute power, social connection and interaction – and you will begin to understand why the industry is calling Cloud Computing the next step in the industry.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDiudB_7OWI/AAAAAAAAANg/aFjJo35pyfE/s1600/Server.jpg"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 198px; FLOAT: left; HEIGHT: 215px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492331559354317154" border="0" alt="" src="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDiudB_7OWI/AAAAAAAAANg/aFjJo35pyfE/s320/Server.jpg" /&gt;&lt;/a&gt;Data Services: &lt;/strong&gt;It is about bridging data across the web between clients and servers. Data Services package data into RESTful style services that transport data to client applications via structured, parse-able text feeds in Atom (XML) or Json format. They also provide data access business logic that can be used to restrict data operations (CRUD). The foundation of all these services is called Windows Communication Foundation (WCF) and from this technology branches all the data related technologies like WCF Data Services, RIA Data Services, and OData. &lt;div&gt;&lt;a href="http://microsoftpdc.com/Sessions/FT12"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Talking Points: Pablo Castro shows a Json / JQuery demo (at 20 min in) that has the browser providing the data proxy; at 34 minutes in is a data service server construction demo: &lt;a href="http://microsoftpdc.com/Sessions/FT12"&gt;FT12: ADO.NET Data Services: What’s new with the RESTful data services framework&lt;/a&gt;. You can also see, live, the limits of JavaScript debugging tools.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Data Abstraction:&lt;/strong&gt; In modern .NET applications nobody programs SQL statements directly against the database. Instead, developers use tools like Entity Framework, n-hibernate or IdeaBlade to build an object based data abstraction layer. The abstraction layer simplifies the code that provides data operations CRUD and protects your applications from changes in the underlying database table and column structures (schema) that is necessary for physical storage and performance. This layer also provides metadata about the data source, which make it possible to create tooling to generate code and documentation from an empty data source. I think that all modern .NET software should take advantage of a data abstraction layer.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Talking Points: &lt;a href="http://microsoftpdc.com/Sessions/FT10"&gt;FT10: Evolving ADO.NET Entity Framework in .NET 4 and Beyond&lt;/a&gt;. I love this talk; it is all demos that show how Microsoft is listening to developers and tuning the Entity Framework to address real world development issues. Don Box and Chris Anderson show in &lt;a href="http://microsoftpdc.com/Sessions/P09-04"&gt;Data Programming and Modeling for the Microsoft .NET Developer&lt;/a&gt; that you can create a database from the model or from code. It is worth watching.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;strong&gt;Data Storage:&lt;/strong&gt; Microsoft’s enterprise solution for relational data storage is SQL Server 2008. However data can be stored and accessed in other data providers like XML or the file system. If your application has more that one database (maybe resulting from the need to run disconnected), synchronization is going to be one of your largest problems. Luckily there is an app for that: Microsoft Sync Framework.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Talking Points: Mark Scurrell’s talk &lt;a href="http://microsoftpdc.com/Sessions/SVC23"&gt;SV23: Using the Microsoft Sync Framework to Connect Apps to the Cloud&lt;/a&gt; is loaded with demos that show database synchronization in action, and very little code is involved.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Isolated Storage vs. Client Resource Access&lt;br /&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div&gt;Thin clients use HTTP cookies to store information on the client. This small bit of text is stored somewhere in your local hard drive, deep in the file system. Browsers are known for running their applications in a sandbox. This is used to promote secure operation of untrusted programs. The sandbox constraint is also true for rich client plug-ins . They run in a sandbox and have no access to client resources until the user gives permission. Silverlight applications have access to a larger storage area (1 MB , with the user’s permission) referred to as isolated storage. The isolated storage area can be used to store configuration information and user setting preferences. It can also be used to cache local record sets, making it possible to work in a disconnected mode.&lt;br /&gt;&lt;br /&gt;A Silverlight application, with the user’s permission, can be installed to the desktop from the browser with a single mouse click and run in &lt;a href="http://team.interknowlogy.com/blogs/danhanan/archive/2009/11/18/silverlight-4-take-advantage-of-full-trust.aspx"&gt;full trust or out-of-browser mode&lt;/a&gt;. With elevated trust, the Silverlight application can now access all your client resources and function as a thick client. Some of the more common scenarios here are to access COM software components (Microsoft Office, VB 6 Programs) and read and write to the local file system.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To really understand the ease of programming Out Of Browser (OOB) applications and the power of having the same code function as thin client and thick client, watch Joe Stegman’s talk &lt;a href="http://microsoftpdc.com/Sessions/CL20"&gt;CL20: Improving and Extending the Sandbox with Microsoft Silverlight 4&lt;/a&gt;. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-8829176351500431700?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/8829176351500431700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=8829176351500431700&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8829176351500431700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8829176351500431700'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2010/01/what-i-learned-from-pdc-server.html' title='What I Learned from PDC - Server Technologies'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_s1N_RQkyQXU/TDiudB_7OWI/AAAAAAAAANg/aFjJo35pyfE/s72-c/Server.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-7447331127803395213</id><published>2009-12-26T13:01:00.001-05:00</published><updated>2010-07-10T13:17:33.472-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='RIA Services'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><category scheme='http://www.blogger.com/atom/ns#' term='data services'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>What I Learned from PDC - Domain Technologies (continued)</title><content type='html'>&lt;strong&gt;Controller Model:&lt;/strong&gt; All the commanding and navigation instructions are implemented at this level. Think of this layer as reacting to menu clicks, hyperlinks or changes of URL address. The controller is one of the central models in ASP.NET MVC (Model View Controller) and in a good implementation will defer many of the control logic decisions to the domain model. In ASP.NET MVC, the controller is used to return a view based on an action, and will typically consult the model to do so. In other applications the controller is not as pronounced, however there are usually classes that expose functions to act as command targets.&lt;br /&gt;&lt;br /&gt;Talking Points: Exposing ICommand for Silverlight has simplified the implementation of a control pattern. Best examples using the controller pattern are &lt;a href="http://microsoftpdc.com/Sessions/FT59"&gt;FT59: ASP.NET MVC 2: Ninjas Still on Fire Black Belt Tips&lt;/a&gt; by Scott Hanselman, &lt;a href="http://microsoftpdc.com/Sessions/FT22"&gt;FT22: Microsoft ASP.NET MVC 2: The New Stuff&lt;/a&gt; by Stephen Walther, &lt;a href="http://microsoftpdc.com/Sessions/CL22"&gt;CL22: Advanced Topics for Building Large-Scale Applications with Microsoft Silverlight &lt;/a&gt;by John Papa and &lt;a href="http://microsoftpdc.com/Sessions/CL21"&gt;CL21: Building Amazing Business Applications with Microsoft Silverlight and Microsoft .NET RIA Services &lt;/a&gt;by Brad Abrams. None of these talks show you how to build a controller, but they all use an MVC pattern to build their application.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Data Proxy:&lt;/strong&gt; The Data Proxy layer is a service oriented architecture (SOA) where the communication is with a data source. There is no limit to the data proxies in this layer. In fact there is no limit to the number services your domain can subscribe or publish to. Proxies can be generated automatically by querying metadata about the WCF service. Proxies are class based representations that model the WCF services API. The abstraction is so good, you are hardly aware that you are using a service on a remote server as you program. Proxies can be generated for anything that has a communication contract. The contract is typically expressed in metadata and there are tools for translating the metadata into code that implements the contract explicitly.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 273px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492325579410919362" border="0" alt="" src="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDipA8-UT8I/AAAAAAAAANI/96CZqzVBVps/s400/Aside.jpg" /&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 268px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492325595213878786" border="0" alt="" src="http://4.bp.blogspot.com/_s1N_RQkyQXU/TDipB32CVgI/AAAAAAAAANQ/aZ3uHn4OLAk/s400/ResourceCentric.jpg" /&gt;&lt;br /&gt;This layer is all about communication. The pictures above were taken from Yavor Georgiev’s talk: &lt;a href="http://microsoftpdc.com/Sessions/CL06"&gt;CL06: Networking and Web Services in Silverlight&lt;/a&gt;. The first picture shows the technology layers that .NET WCF provides. The programming model is built over a TCP/IP based protocol. The second picture shows the spectrum of communication applications. Yavor discusses the interaction between communication and different types of applications, from transactional data systems to multicast video systems. Generally speaking, WCF RIA services is the Microsoft technology of choice for building Silverlight rich clients and there are several talks showing this.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Talking Points: See &lt;a href="http://microsoftpdc.com/Sessions/FT12"&gt;FT12: ADO.NET Data Services: What’s new with the RESTful data services framework&lt;/a&gt; Pablo Castro’s client demo (at 44 min in). For an intro to RIA services: &lt;a href="http://microsoftpdc.com/Sessions/CL21"&gt;CL21: Building Amazing Business Applications with Microsoft Silverlight and Microsoft .NET RIA Services&lt;/a&gt; with Brad Abrams. You can tell from this talk the Microsoft is shaping this technology to create Line of Business CRUD applications. You can dive below the surface with &lt;a href="http://microsoftpdc.com/Sessions/CL07"&gt;CL07: Mastering Microsoft .NET RIA Services&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-7447331127803395213?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/7447331127803395213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=7447331127803395213&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/7447331127803395213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/7447331127803395213'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/12/what-i-learned-from-pdc-domain_26.html' title='What I Learned from PDC - Domain Technologies (continued)'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_s1N_RQkyQXU/TDipA8-UT8I/AAAAAAAAANI/96CZqzVBVps/s72-c/Aside.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-7913050031678369196</id><published>2009-12-22T12:42:00.004-05:00</published><updated>2010-07-12T18:26:22.989-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='domain model'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><title type='text'>What I Learned from PDC - Domain Technologies</title><content type='html'>The domain is the brain or personality of the application and is usually built with the help of a Subject Matter Expert (SME).&lt;br /&gt;&lt;br /&gt;I like to think of the domain as having the real knowledge of the application and the Client and Server components as providing input/output services. Think of the case where a text box control is doing input validation. The code in the control can be kept simple, it just needs to verify that the text typed in by the user conforms to a validation rule, and if it does not, display some type of message.&lt;br /&gt;&lt;br /&gt;An implementation that binds the control to a text string might also execute validation logic in the On-Click code behind method. An implementation that binds the control to a property lets the code in the control stay generic, and keeps all the validation logic in the domain model where it can be easily maintained. This separation of concerns is the ‘S’ of the ‘SOLID’ design principle and you can learn about the other components (OLID) &lt;a href="http://www.hanselman.com/blog/HanselminutesPodcast145SOLIDPrinciplesWithUncleBobRobertCMartin.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When you create a domain model that uses the vocabulary of your SME, and solves problems using the processes the SME would use, then the rest of the application becomes easier to build. The Client and Server layers become tools to visualize your domain model or persist your domain model.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDik7qtIn6I/AAAAAAAAAM4/GwiA3fFVrW8/s1600/DomainModel.jpg"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 198px; FLOAT: left; HEIGHT: 215px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492321090561154978" border="0" alt="" src="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDik7qtIn6I/AAAAAAAAAM4/GwiA3fFVrW8/s320/DomainModel.jpg" /&gt;&lt;/a&gt;Domain Model: The Domain Model executes the formal business logic and should be the primary location for all the application state transition rules. Very few talks have time to develop a Domain Model, however if you watch talks that focus on language features, LINQ, Rx or parallel computing they are full of examples showing how domain modeling is becoming more declarative and less imperative. That is, software design is evolving into describing what you need the computer to do instead of traditionally telling the computer how to do it. .NET is evolving to merge dynamic, functional and object oriented programming models into the platform. The declarative slant in coding allows the .NET platform to make decisions about how to execute the code at runtime, to take advantage of system resources like multiple CPUs or resources in the Cloud.&lt;br /&gt;&lt;br /&gt;Talking Points: Microsoft talks do not focus on the domain model at all. The only talk I found that fits the definition is &lt;a href="http://microsoftpdc.com/Sessions/CL36"&gt;Cl36: Deep Dive on Bing Maps Silverlight Control&lt;/a&gt; because it focuses on the domain of mapping, however the domain is so well defined it is delivered as a GUI control and a service. Instead look to the language features to help you model your domain: &lt;a href="http://microsoftpdc.com/Sessions/FT11"&gt;FT11: Future Directions for C# and Visual Basic&lt;/a&gt;. Developers should be aware of a new (or maybe very old if you know LISP) way of programming &lt;a href="http://microsoftpdc.com/Sessions/FT20"&gt;FT20: F# for Parallel and Asynchronous Programming&lt;/a&gt; , languages for Data Modeling &lt;a href="http://microsoftpdc.com/Sessions/FT34"&gt;FT34: Microsoft Project Code Name “M”: The Data and Modeling Language&lt;/a&gt;, Parallel Computing Platform: &lt;a href="http://microsoftpdc.com/Sessions/P09-09"&gt;P09: Manycore and the Microsoft .NET Framework 4: A Match Made in Microsoft Visual Studio 2010 &lt;/a&gt;and Erik Meijer VTL04: &lt;a href="http://microsoftpdc.com/Sessions/VTL04"&gt;Rx: Reactive Extensions for .NET&lt;/a&gt;. Rx technology was the language innovation of the show. &lt;a href="http://channel9.msdn.com/posts/Charles/Erik-Meijer-Rx-in-15-Minutes/"&gt;Learn about Rx in 15 min here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I will cover the Controller Model and Data Proxy in the next post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-7913050031678369196?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/7913050031678369196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=7913050031678369196&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/7913050031678369196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/7913050031678369196'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/12/what-i-learned-from-pdc-domain.html' title='What I Learned from PDC - Domain Technologies'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_s1N_RQkyQXU/TDik7qtIn6I/AAAAAAAAAM4/GwiA3fFVrW8/s72-c/DomainModel.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2521504860325010773</id><published>2009-12-18T11:44:00.004-05:00</published><updated>2010-07-10T12:45:21.430-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rich client'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><category scheme='http://www.blogger.com/atom/ns#' term='View Model'/><title type='text'>What I Learned from PDC - Client Technologies</title><content type='html'>&lt;strong&gt;Client Technologies&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There are many different client side technologies in the Microsoft ecosystem, and each has evolved to meet niche markets and end user needs, including video game, business apps, reports, and web page browsing. The defining technology of the client is probably how the view is rendered and the device’s ability to interact with that rendering.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDiiBHs6VaI/AAAAAAAAAMw/GJXJ5xAnC1Y/s1600/Client.jpg"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 208px; FLOAT: left; HEIGHT: 167px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492317885709309346" border="0" alt="" src="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDiiBHs6VaI/AAAAAAAAAMw/GJXJ5xAnC1Y/s320/Client.jpg" /&gt;&lt;/a&gt;View Rendering:&lt;/strong&gt; Microsoft provides two different solutions for rendering a GUI: the thin client solution is HTML/JavaScript rendered inside a web browser, the rich client solution is XAML, which can be rendered in a web browser via a Silverlight plug-in, or as part of a thick client application using WPF. So XAML is dual purpose with the caveat that the end user must install the Silverlight plug-in (5 MB, 30 second, one time operation, just like Flash). Simple HTML has more range, because it runs in any browser, but when you start adding CSS and JQuery libraries (and other fancy things) you begin to limit yourself to a subset of browsers, IE7,IE8,Firefox,… again if you can control your target, this is not a problem. The Silverlight plug-in is designed to remove browser incompatibilities and create a UI that is “run anywhere” including Mac and Linux.&lt;br /&gt;&lt;br /&gt;Talking Points: &lt;a href="http://microsoftpdc.com/Sessions/FT29"&gt;FT29: Microsoft AJAX Library, jQuery, and Microsoft Visual Studio 2010&lt;/a&gt; Stephen Walther, shows how to build thin HTML clients with a new open source AJAX library, including 40 client controls, Open Source.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;View Model:&lt;/strong&gt; The purpose of a View Model is to shape your domain model to a view rendering technology. You must manage the interaction controls, events, value conversion, input validation, and general state of the GUI controls rendering using this model. In WPF/Silverlight, the View Model provides a site to bind the UI to the domain model. Sometimes perceived as additional work by programmers, the decoupling of the view from the domain model actually simplifies the implementation of the client GUI by providing a site for view logic that is independent of the domain. Some good examples are multi-lingual UI’s, currency conversion, hiding sections based on roles, and changing screen presentations based on task, expertise or device size. This separation also makes the application much more testable using an automated test suite.&lt;br /&gt;&lt;br /&gt;Talking Points: Newly added ICommand support was the final step in making the view rendering and the view model truly independent and testable. Some Silverlight talks that discuss View Models are &lt;a href="http://microsoftpdc.com/Sessions/CL19"&gt;Cl19: Building Line of Business Applications with Microsoft Silverlight 4&lt;/a&gt; and John Papa’s talk &lt;a href="http://microsoftpdc.com/Sessions/CL22"&gt;Cl22: Advanced Topics for Building Large-Scale Applications with Microsoft Silverlight&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2521504860325010773?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2521504860325010773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2521504860325010773&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2521504860325010773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2521504860325010773'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/12/what-i-learned-from-pdc-part-4.html' title='What I Learned from PDC - Client Technologies'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_s1N_RQkyQXU/TDiiBHs6VaI/AAAAAAAAAMw/GJXJ5xAnC1Y/s72-c/Client.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-5719654832307007569</id><published>2009-12-05T11:36:00.002-05:00</published><updated>2010-07-10T12:46:26.138-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><title type='text'>What I Learned from PDC - Service Oriented Architecture</title><content type='html'>&lt;strong&gt;Mapping Functionality into Abstract Software Components&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Each of the presentations at PDC are designed to discuss some aspect of Microsoft’s packaged technology: ASP.NET, SQL Server, Silverlight, Entity Framework, LINQ &amp;amp; PLINQ, MVC, WPF, WCF Data service, Azure, … Windows 7. In every case, the presentations show code samples on how to use that technology, and in the process they casually introduce some abstract software architecture concept (View Models, Data Proxies, Domain Models…) to help illustrate the technology.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDiU4oG5ijI/AAAAAAAAAMo/bqdLjnCtmLk/s1600/Depth.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 136px; FLOAT: left; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492303446138260018" border="0" alt="" src="http://2.bp.blogspot.com/_s1N_RQkyQXU/TDiU4oG5ijI/AAAAAAAAAMo/bqdLjnCtmLk/s400/Depth.png" /&gt;&lt;/a&gt;Application Depth&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I have extracted the software concepts from all those talks and constructed an application depth stack that maps these functional requirements to software layers. These layers combine the “best practices” in software design from ASP.NET MVC, WPF &amp;amp; Silverlight applications and also include technologies that are common to all solutions like WCF Data Services, SQL Server and Entity Framework. The software component names are not official and the code boundaries between them in many cases are not precise, but they are useful in categorizing the Microsoft technologies that are used to construct and execute each layer.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Client, Domain and Server Models&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I broke the sections up into Client, Domain, and Server. The Domain section can execute on the client or the server. When deployed as a thin client, the Domain logic is executed on the Server, but when deployed as a rich client the Domain executes on the Client and helps manage State. Server components are traditional data access services. Using data services is now Microsoft’s preferred way of connecting to data. Data services use simple web protocols to request and transport data even if you are consuming data on the same machine as the client. The service can be accessed just by passing a URL. Data access is provided using proxy service “wrappers” that provide an API by ingesting the META data about the service. These are the building blocks of a Service Oriented Architecture (SOA).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Best Practices? For My Purposes They Are!&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I am not saying that each of these abstract software components need to physically exist in order for you to have a well designed or valid .NET application. Most CRUDS database solutions (Create, Read, Update, Delete, Search) are put together in a forms-over-data software architecture and do not implement all of these components. I am saying that during the design/development phase of a solution, I believe that the most developers should at least think about these functional areas, even if it is just to dismiss them as unnecessary.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-5719654832307007569?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/5719654832307007569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=5719654832307007569&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5719654832307007569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5719654832307007569'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/12/what-i-learned-from-pdc-part-3.html' title='What I Learned from PDC - Service Oriented Architecture'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_s1N_RQkyQXU/TDiU4oG5ijI/AAAAAAAAAMo/bqdLjnCtmLk/s72-c/Depth.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-5874836135524962480</id><published>2009-11-30T11:23:00.003-05:00</published><updated>2010-07-12T18:31:41.056-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rich client'/><category scheme='http://www.blogger.com/atom/ns#' term='thin client'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><category scheme='http://www.blogger.com/atom/ns#' term='thick client'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='asynchronous'/><category scheme='http://www.blogger.com/atom/ns#' term='synchronous'/><title type='text'>What I Learned from PDC - Thick, Thin and Rich Clients</title><content type='html'>These three paradigms of application deployment try to optimize between application reach and application experience.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;a href="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDiSvG0uP8I/AAAAAAAAAMg/SfJl7vQLzSU/s1600/Bredth.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 181px; FLOAT: left; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492301083561574338" border="0" alt="" src="http://1.bp.blogspot.com/_s1N_RQkyQXU/TDiSvG0uP8I/AAAAAAAAAMg/SfJl7vQLzSU/s400/Bredth.png" /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Thick Clients&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Thick clients have easy access to client resources (file system, local databases, USB ports, and peripherals). They are also characterized by running their code on the local CPU. Thick clients do not need to be connected to the internet to run, but they can be connected to resources on the internet. Using local resources and memory allows them to be ‘stateful’, which means the application can easily remember the actions of the user as the user progresses. Behavior like dynamically enabling menus, progressing through a wizard dialog or cut/copy &amp;amp; paste are examples of statefullness. Microsoft provides 2 technologies to create thick client applications: Winforms (Win32 &amp;amp; GDI) and WPF.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Thin Clients&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;‘Thin client’ was the original name given to web browser based applications. This paradigm has all the code executing on the server, and the code is designed to deliver information to a web browser (HTML and JavaScript), and the browser will render the information as a web page. Microsoft markets ASP.NET and ASP.NET MVC as platforms that deliver thin client solutions. These applications have achieved wide popularity because of their reach -- anyone with a browser and an internet connection can access this information -- regardless of the hardware or operating system. Developing richness in these applications requires the use of Cascading Style Sheets (CSS), Ajax, JQuery and JavaScript.&lt;br /&gt;&lt;br /&gt;Browser based applications are not really stateful on the client (with the exception of cookies and session tokens), so with each user interaction, the local HTML, stored in the browser’s in-memory Document Object Model (DOM), is modified or refreshed dynamically. Ajax and JQuery are technologies used to modify the contents of the DOM (letting it refresh the screen after the change) and can be used to create some amazing GUIs that rival thick client applications. Thin clients have two weaknesses:&lt;br /&gt;1. For security reasons, they are forced to run in the browser’s “sandbox”, which limits access to local system resources.&lt;br /&gt;2. Building a rich GUI is difficult, and making that GUI testable is extremely difficult.&lt;br /&gt;&lt;br /&gt;Based on my conversations at PDC, I found that programmers who quickly adopt the Ajax / JQuery route to provide richness have spent years creating UIs by programming JavaScript or HTML in ASP.NET applications. These technologies naturally fit into their way of thinking and their existing knowledge and experience.&lt;br /&gt;&lt;br /&gt;I have seen solutions that deploy thin client / server applications onto a single box to try and get the advantages of the thick client. This can be done by using a Web Server (like IIS) and works well in applications that do NOT need to access local machine resources. This approach has difficulty synchronizing with a data source on the web. Integrating to local resources from the browser “sandbox” eventually requires some sort of browser plug-in that the end user trusts and has given permission to access the resources.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Rich Clients&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Rich client applications, and Silverlight in particular, try to blend what is best about thick and thin clients. Microsoft accomplishes this by making Silverlight a 5 MB subset of the .NET platform, optimized to run on any OS (Windows, Mac, Linux) instead of targeting any particular browser. Silverlight is delivered to the browser as a plug-in (similar to Flash or Adobe Reader) and can use the browser’s resources and DOM.&lt;br /&gt;&lt;br /&gt;Applications written using Silverlight can also be installed on the desktop and access local machine resources. So, like thick client solutions, rich clients run code locally and offer GUI features like drag/drop, animation, threading, and statefulness. They can also run connected or disconnected and can access local resources. Like thin client solutions, rich clients are accessible via a web browser, deliverable without a separate install, can detect newer versions and update automatically. Silverlight has the advantage of using the same programming environment as the server. This is VERY important.&lt;br /&gt;&lt;br /&gt;As a developer, what I really like about Silverlight is that you can use the same code regardless if it is running in a browser or on the desktop. All the development can be done in WPF (XAML) and C#, so I do not need to be expert in a lot of different authoring technologies. Having the common .NET platform on both the client and the server makes it easier for me to optimize the solution’s performance just by moving code between the client project and the server project. Silverlight is aware of where it is running, which makes it easier to add and remove application features at runtime by querying the environment dynamically and not having to trust that the user installed the correct version. Lastly, the entire solution, from GUI to database access, can have a built-in automated test suite to assure quality and performance.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Asynchronous vs. Synchronous Communication&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Asynchronous and synchronous communications are shown in boxes on the diagram. Silverlight enforces an asynchronous communications model when communicating with the server. That is to say that GUI interaction is not blocked when you are loading data or web pages. So while the user is performing tasks like navigation or mouse over, in the background Silverlight can be running calculations, doing analysis, loading data or any other programming task. Thin client solutions, including ASP.NET MVC, tend to run in a synchronous manner, which is where the user performs some action, the request is passed to the server, then the server sends a page of information back to the client, and the browser re-renders the page. Ajax and JQuery allow the application to send requests to the server that re-render sections of the page, but you cannot interact with those sections while they are ‘waiting’ for information. Microsoft introduced GUI controls that allow the Silverlight UI to behave synchronously by showing a progress bar and blocking user interaction. Blocking has it uses, but to me this feels like a step backward.&lt;br /&gt;&lt;br /&gt;The challenge is to design UIs that are still functional while waiting for data. Think of iTunes - while songs are downloading, iTunes does not prevent you from accessing all of its features. Building a good GUI that blends the menu / work-area paradigm of the desktop with the hyperlink / URL navigation of the web is very tricky. Users can get focused on the details so quickly (colors and styles) that the things that make a very useable GUI, (layout, workflow, transitions and statefulness) do not get detailed consideration until after deployment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-5874836135524962480?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/5874836135524962480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=5874836135524962480&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5874836135524962480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5874836135524962480'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/11/what-i-learned-from-pdc-part-2.html' title='What I Learned from PDC - Thick, Thin and Rich Clients'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_s1N_RQkyQXU/TDiSvG0uP8I/AAAAAAAAAMg/SfJl7vQLzSU/s72-c/Bredth.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-235148415755712987</id><published>2009-11-25T10:52:00.003-05:00</published><updated>2010-07-10T12:47:53.687-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='PDC'/><category scheme='http://www.blogger.com/atom/ns#' term='architecture'/><title type='text'>What I Learned from PDC - An Overview</title><content type='html'>I attended MIX07, PDC07, MIX08, PDC08, and MIX09 online, so I have been following the Microsoft technical narrative for the last 3 years. I attended PDC09 live. One of my goals was to organize the technical narrative, which is normally presented product / technology centric into the components of a single application centric model.&lt;br /&gt;&lt;br /&gt;For the past decade, my customers were looking for applications that offered the best of all experiences. Because they were unconstrained by technology in their thinking, they asked for features that were an amalgam of Web, Phone and Desktop applications, their ‘ideal’ application. I have been looking for a set of technologies that can deliver all these features from a single code base. I could see Microsoft was approaching such a solution, and at PDC09 many of these pieces came together. I created a diagram to help navigate the changing face of Microsoft technology in the light of customers’ Web/Desktop visions.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 300px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5492295839816749922" border="0" alt="" src="http://4.bp.blogspot.com/_s1N_RQkyQXU/TDiN94WiE2I/AAAAAAAAAMY/F49d-P4QFU8/s400/Dynamic+Domain+Applications.png" /&gt; If you find this diagram hard to read, don't worry -- it will be broken down into readable pieces in the blog posts that follow.&lt;/p&gt;&lt;p&gt;The ‘ideal’ application in my customers’ eyes can run over the web, or run disconnected on a laptop without changing the GUI or user experience. Being connected to the internet should only be necessary to read or share data, but not a requirement to complete work. It should also be able to run on nearly any device with any screen size, a server, desktop, laptop, or a phone. Software components must be agnostic of where they are running (client or server) and cannot duplicate logic. The software community describes this style of application as Line of Business (LOB) apps; I do not like the term but it looks like it is getting a lot of traction on the web. Two archetypes for this LOB style of application are a traveling salesman and a soldier deployed in Afghanistan.&lt;br /&gt;&lt;br /&gt;The diagram above is used to map the Microsoft technologies to support the LOB application. Not everything discussed at PDC09 has a place in this mapping, but I think you can get more out of the talks if you keep this diagram in mind while you pick and choose among the talks. The diagram shows, on the left side, the breath and depth of an application, on the right side, the technology and tooling available to construct, maintain and deploy the application. The functional layer (vertically down the center) was extracted from and reinforced by many of the PDC talks.&lt;br /&gt;&lt;br /&gt;A well designed end-to-end .NET application will account for all of these functional layers in each of the technology stacks. As developers (and users), we can see the value in a software architecture that includes GUI, Client/Server side validation, Logic and Rules, Command/Navigation control, Data services, Networking, Object Relation Mapping, and Persistence.&lt;br /&gt;&lt;br /&gt;Vertically the diagram shows a progression from End User to Application Hosting, via a set of functional requirements (Functional Layer). Horizontally, there is a set of four technology stacks, each with a unique perspective on building software.&lt;br /&gt;Horizontally I have juxtaposed 4 diagrams each focusing on a different aspect of the software development process -- breadth, depth, platform, and tooling. Here are some working definitions:&lt;br /&gt;•Breadth: who is the audience and how do I reach them, how do they plan to access my solution?&lt;br /&gt;•Depth: what tasks do my users do and under what conditions, how do I make the application easy to use?&lt;br /&gt;•Platform: what are the technologies I can use to build a deployable, maintainable, extensible solution, successfully using the skills of my development staff?&lt;br /&gt;•Tooling: what are the tools available to assure that I am producing the solution efficiently and correctly?&lt;br /&gt;&lt;br /&gt;My goal is to explore the subset of the Microsoft technologies presented at PDC in the context of building a solution that can run thinly over the web, or disconnected as a thick client reusing as much code and common technologies / tooling as possible. The result should be a road map of the essential Microsoft technologies you should be aware of in order to build a modern .NET client/server application.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-235148415755712987?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/235148415755712987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=235148415755712987&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/235148415755712987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/235148415755712987'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/11/what-i-learned-from-pdc-part-1.html' title='What I Learned from PDC - An Overview'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_s1N_RQkyQXU/TDiN94WiE2I/AAAAAAAAAMY/F49d-P4QFU8/s72-c/Dynamic+Domain+Applications.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-183829608366331305</id><published>2009-08-31T09:16:00.008-04:00</published><updated>2010-07-12T18:33:25.272-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='View Model'/><title type='text'>M-V-VM Product Configuration</title><content type='html'>&lt;p&gt;Deb and I have created many solutions that support sales or engineering efforts. Each application is a little different, driven by the unique aspects of the product we are selling/designing. We have built systems to sell cars, to quote multi-million dollar communications infrastructure projects, to design chemical plants and gear boxes.&lt;br /&gt;&lt;br /&gt;&lt;object width="582" height="461" class="BLOG_video_class" id="BLOG_video-a2a129a9c5f1b299" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v12.nonxt4.googlevideo.com/videoplayback?id%3Da2a129a9c5f1b299%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190912%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D4C9DBD7D21503852728DF90644208C1E85D522D3.20EDA591F49164E0FE9673C76C06E5EB6B17832F%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Da2a129a9c5f1b299%26offsetms%3D5000%26itag%3Dw160%26sigh%3DTGJ5z4qPscEqwnYMjyhkL0PZNEI&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="582" height="461" bgcolor="#FFFFFF"flashvars="flvurl=http://v12.nonxt4.googlevideo.com/videoplayback?id%3Da2a129a9c5f1b299%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190912%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D4C9DBD7D21503852728DF90644208C1E85D522D3.20EDA591F49164E0FE9673C76C06E5EB6B17832F%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Da2a129a9c5f1b299%26offsetms%3D5000%26itag%3Dw160%26sigh%3DTGJ5z4qPscEqwnYMjyhkL0PZNEI&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You do enough of these applications and you start to see a software design pattern. You also realize just how important the role of the subject matter expert is in helping you create a successful application. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Our first Silverlight product configuration solution is a Cookie Designer. With a lifetime of experience eating cookies and a trip to the store to read the packaging, I now consider myself a subject matter expert. You can test drive the program &lt;a href="http://www.componentart.com/community/competition2009/details.aspx?id=1074&amp;amp;return=contestants.aspx%3fsort%3dentrydate%26dir%3ddesc%26page%3d1"&gt;HERE.&lt;/a&gt; &lt;/p&gt;&lt;p&gt;The Cookie Designer is an entry in the Summer Silverlight Coding Competition -- please try it and vote for our solution. Community points are an important part of the judging in this contest. &lt;/p&gt;&lt;p&gt;Our cookie product configuration solution is composed of a set of ingredients that can be combined without any mutually exclusive constraints. Anyone for cinnamon oatmeal dark chocolate chunk? &lt;/p&gt;&lt;p&gt;The secret to creating a convincing picture is to have each ingredient on its own separate layer and to make visible the layers that are involved -- enter the M-V-VM pattern, and in this case used as an adapter / translator between the composition of the model and what is shown. &lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &amp;lt;Canvas x:Name=&lt;span class="str"&gt;"CookieRoot"&lt;/span&gt; Height=&lt;span class="str"&gt;"400"&lt;/span&gt; HorizontalAlignment=&lt;span class="str"&gt;"Center"&lt;/span&gt; VerticalAlignment=&lt;span class="str"&gt;"Center"&lt;/span&gt; Width=&lt;span class="str"&gt;"400"&lt;/span&gt; Clip=&lt;span class="str"&gt;"M0,0L400,0 400,400 0,400z"&lt;/span&gt; RenderTransformOrigin=&lt;span class="str"&gt;"0.5,0.5"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image Height=&lt;span class="str"&gt;"381"&lt;/span&gt; Width=&lt;span class="str"&gt;"404"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"-9"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"8"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Base Cookie.png"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Cinnamon"&lt;/span&gt; Height=&lt;span class="str"&gt;"382"&lt;/span&gt; Width=&lt;span class="str"&gt;"390"&lt;/span&gt; Opacity=&lt;span class="str"&gt;"0.651"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"6"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"13"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Cinnamon.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"PeanutButter"&lt;/span&gt; Height=&lt;span class="str"&gt;"379"&lt;/span&gt; Width=&lt;span class="str"&gt;"385"&lt;/span&gt; Opacity=&lt;span class="str"&gt;"0.478"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"7"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"9"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Peanut Butter.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"ReesesPeanutButter"&lt;/span&gt; Height=&lt;span class="str"&gt;"379"&lt;/span&gt; Width=&lt;span class="str"&gt;"385"&lt;/span&gt; Opacity=&lt;span class="str"&gt;"0.478"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"7"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"9"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Peanut Butter.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Cocoa"&lt;/span&gt; Height=&lt;span class="str"&gt;"387"&lt;/span&gt; Width=&lt;span class="str"&gt;"389"&lt;/span&gt; Opacity=&lt;span class="str"&gt;"0.678"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"5"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"5"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Cocoa.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Oatmeal"&lt;/span&gt; Height=&lt;span class="str"&gt;"380"&lt;/span&gt; Width=&lt;span class="str"&gt;"387"&lt;/span&gt; Opacity=&lt;span class="str"&gt;"0.412"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"6"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"7"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Oatmeal.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Peanuts"&lt;/span&gt; Height=&lt;span class="str"&gt;"377"&lt;/span&gt; Width=&lt;span class="str"&gt;"381"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"9"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"10"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Peanuts.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Raisins"&lt;/span&gt; Height=&lt;span class="str"&gt;"373"&lt;/span&gt; Width=&lt;span class="str"&gt;"370"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"15"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"10"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Raisins.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Pecans"&lt;/span&gt; Height=&lt;span class="str"&gt;"313"&lt;/span&gt; Width=&lt;span class="str"&gt;"302"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"56"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"56"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Pecans.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"Almonds"&lt;/span&gt; Height=&lt;span class="str"&gt;"286"&lt;/span&gt; Width=&lt;span class="str"&gt;"333"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"14"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"59"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Almonds.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"WhiteChocolateChips"&lt;/span&gt; Height=&lt;span class="str"&gt;"351"&lt;/span&gt; Width=&lt;span class="str"&gt;"353"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"18"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"45"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/White Chocolate Chips.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"SemisweetChocolateChips"&lt;/span&gt; Height=&lt;span class="str"&gt;"400"&lt;/span&gt; Width=&lt;span class="str"&gt;"400"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"0"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"0"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Dark Chocolate Chips.png"&lt;/span&gt; RenderTransformOrigin=&lt;span class="str"&gt;"0.5,0.5"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"MilkChocolateChips"&lt;/span&gt; Height=&lt;span class="str"&gt;"351"&lt;/span&gt; Width=&lt;span class="str"&gt;"380"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"7"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"45"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Milk Chocolate Chips.png"&lt;/span&gt; RenderTransformOrigin=&lt;span class="str"&gt;"0.5,0.5"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"MacadamiaNuts"&lt;/span&gt; Height=&lt;span class="str"&gt;"377"&lt;/span&gt; Width=&lt;span class="str"&gt;"354"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"38"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"12"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Macadamia Nuts.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"DarkChocolateChunks"&lt;/span&gt; Height=&lt;span class="str"&gt;"546"&lt;/span&gt; Width=&lt;span class="str"&gt;"456"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"-27"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"-88"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Dark Chocolate Chunks.png"&lt;/span&gt; RenderTransformOrigin=&lt;span class="str"&gt;"0.5,0.5"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"MilkChocolateChunks"&lt;/span&gt; Height=&lt;span class="str"&gt;"546"&lt;/span&gt; Width=&lt;span class="str"&gt;"456"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"-27"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"-88"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Milk Chocolate Chunks.png"&lt;/span&gt; RenderTransformOrigin=&lt;span class="str"&gt;"0.5,0.5"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"WhiteChocolateChunks"&lt;/span&gt; Height=&lt;span class="str"&gt;"546"&lt;/span&gt; Width=&lt;span class="str"&gt;"456"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"-27"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"-88"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/White Chocolate Chunks.png"&lt;/span&gt; RenderTransformOrigin=&lt;span class="str"&gt;"0.5,0.5"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;/Image&amp;gt;&lt;br /&gt;&lt;br /&gt;            &amp;lt;Image x:Name=&lt;span class="str"&gt;"HersheyMiniKisses"&lt;/span&gt; Height=&lt;span class="str"&gt;"134"&lt;/span&gt; Width=&lt;span class="str"&gt;"134"&lt;/span&gt; Canvas.Left=&lt;span class="str"&gt;"134"&lt;/span&gt; Canvas.Top=&lt;span class="str"&gt;"126"&lt;/span&gt; Source=&lt;span class="str"&gt;"Cookie_Images/Hershey Kiss.png"&lt;/span&gt; Visibility=&lt;span class="str"&gt;"Collapsed"&lt;/span&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;/Canvas&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt; font-size: small;&lt;br /&gt;&lt;br /&gt; color: black;&lt;br /&gt;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;&lt;br /&gt;.csharpcode .alt&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt;&lt;br /&gt; width: 100%;&lt;br /&gt;&lt;br /&gt; margin: 0em;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;We were careful to name the XAML elements so they could be controlled through an automated binding statement that is generated when the picture is loaded.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; CookieCanvas_Loaded(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;{&lt;br /&gt;     &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Image oItem &lt;span class="kwrd"&gt;in&lt;/span&gt; CookieRoot.Children)&lt;br /&gt;     {&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt; sName = oItem.Name;&lt;br /&gt;          &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(sName))&lt;br /&gt;          &lt;span class="kwrd"&gt;continue&lt;/span&gt;;&lt;br /&gt;          var oBinding = &lt;span class="kwrd"&gt;new&lt;/span&gt; Binding(sName);&lt;br /&gt;          oBinding.Mode = BindingMode.OneWay;&lt;br /&gt;          oItem.SetBinding(Button.VisibilityProperty, oBinding);&lt;br /&gt;     }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With all this binding now in place the final step is the view model.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CookieVM : ViewModel&lt;br /&gt;&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; CookieVM(Instance oSource)&lt;br /&gt;&lt;br /&gt;            : &lt;span class="kwrd"&gt;base&lt;/span&gt;(oSource)&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnCollectionChanged(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, NotifyCollectionChangedEventArgs e)&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.NewItems.IsNotNull())&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Component oNote &lt;span class="kwrd"&gt;in&lt;/span&gt; e.NewItems.OfType&amp;lt;Component&amp;gt;())&lt;br /&gt;&lt;br /&gt;                    NotifyPropertyChange(oNote.ClassName);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.OldItems.IsNotNull())&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (Component oNote &lt;span class="kwrd"&gt;in&lt;/span&gt; e.OldItems.OfType&amp;lt;Component&amp;gt;())&lt;br /&gt;&lt;br /&gt;                    NotifyPropertyChange(oNote.ClassName);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Cinnamon&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Cinnamon"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility PeanutButter&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"PeanutButter"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility ReesesPeanutButter&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"ReesesPeanutButter"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Cocoa&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Cocoa"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Oatmeal&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Oatmeal"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Peanuts&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Peanuts"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Raisins&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Raisins"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility HersheyMiniKisses&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"HersheyMiniKisses"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Pecans&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Pecans"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility Almonds&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"Almonds"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility DarkChocolateChunks&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"DarkChocolateChunks"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility MilkChocolateChunks&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"MilkChocolateChunks"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility WhiteChocolateChunks&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"WhiteChocolateChunks"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility WhiteChocolateChips&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"WhiteChocolateChips"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility SemisweetChocolateChips&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"SemisweetChocolateChips"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility MilkChocolateChips&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"MilkChocolateChips"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Visibility MacadamiaNuts&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; DoesChildOfClassExist(&lt;span class="str"&gt;"MacadamiaNuts"&lt;/span&gt;) ? Visibility.Visible : Visibility.Collapsed; }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-183829608366331305?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/183829608366331305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=183829608366331305&amp;isPopup=true' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/183829608366331305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/183829608366331305'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/08/m-v-vm-product-configuration.html' title='M-V-VM Product Configuration'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-9021325943011555256</id><published>2009-08-01T10:33:00.002-04:00</published><updated>2009-08-19T10:56:32.889-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Expression Blend 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Converting SketchFlow to Production'/><category scheme='http://www.blogger.com/atom/ns#' term='SketchFlow'/><title type='text'>Converting SketchFlow to Production</title><content type='html'>Deb:  I was really excited to start working with Blend 3 with &lt;span id="SPELLING_ERROR_0" class="blsp-spelling-error"&gt;SketchFlow&lt;/span&gt;!  I had seen videos from MIX 09 demoing &lt;span id="SPELLING_ERROR_1" class="blsp-spelling-error"&gt;SketchFlow&lt;/span&gt; and was disappointed it wasn't in the first release of Blend 3.  Finally I was going to get a chance to try it myself.&lt;br /&gt;&lt;br /&gt;I had a few learning pains, working with the &lt;span id="SPELLING_ERROR_2" class="blsp-spelling-error"&gt;SketchFlow&lt;/span&gt; Map - the documentation was a little sketchy (pardon the pun).  I also had a problem getting the navigation to work right until I learned about right-clicking on the button and going to the bottom of the menu to tell it where to navigate to.  Once I learned that, it was amazingly easy to setup a prototype project.  I was really pleased with the overall tool; I was able to build a nice prototype in a relatively short period of time.&lt;br /&gt;&lt;br /&gt;My disappointment has come as I try to convert this prototype to production.  I hadn't read ahead in the help documentation about how to do this because I assumed it would be relatively straight-forward.  Imagine my surprise when I found a series of 16 steps that had me deleting files, navigating to obscure folders in the &lt;span id="SPELLING_ERROR_3" class="blsp-spelling-error"&gt;SDK&lt;/span&gt; to include references, and editing code in Notepad!  The best advice I received in this series of steps was Step One: backup your project.  After an hour of tedious effort, I got nothing.  The project wouldn't run.&lt;br /&gt;&lt;br /&gt;So I googled 'converting &lt;span id="SPELLING_ERROR_4" class="blsp-spelling-error"&gt;sketchflow&lt;/span&gt; to production' and tapped into a conversation within the &lt;span id="SPELLING_ERROR_5" class="blsp-spelling-error"&gt;Silverlight&lt;/span&gt; community about just how ready for &lt;span id="SPELLING_ERROR_6" class="blsp-spelling-error"&gt;primetime&lt;/span&gt; &lt;span id="SPELLING_ERROR_7" class="blsp-spelling-error"&gt;SketchFlow&lt;/span&gt; really is.  Some people are happy to have such a powerful prototyping tool at their disposal, but say that when you are ready to build the application for real you will need to build it from scratch.  Others range from disappointment to outrage, feeling Microsoft rushed &lt;span id="SPELLING_ERROR_8" class="blsp-spelling-error"&gt;Sketchflow&lt;/span&gt; out before it was really finished, not taking it through the final, critical step of conversion to production.&lt;br /&gt;&lt;br /&gt;Me, I've turned my prototype project over to Steve, the Developer, to see how much he can convert and how much effort is required to convert it.  We will let you know in a later post what we learn.&lt;br /&gt;&lt;br /&gt;Meanwhile, I will be rebuilding the prototype from scratch, as a new project.  I will also investigate getting access to the 'sketchy styles' from a normal &lt;span id="SPELLING_ERROR_9" class="blsp-spelling-error"&gt;Silverlight&lt;/span&gt; project.  It seems to me that much of the value of &lt;span id="SPELLING_ERROR_10" class="blsp-spelling-error"&gt;SketchFlow&lt;/span&gt; would be delivered by the styles alone.  Now if creating navigation was only as easy in a regular &lt;span id="SPELLING_ERROR_11" class="blsp-spelling-error"&gt;Silverlight&lt;/span&gt; project..........&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-9021325943011555256?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/9021325943011555256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=9021325943011555256&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/9021325943011555256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/9021325943011555256'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/08/converting-sketchflow-to-production.html' title='Converting SketchFlow to Production'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-167379801424123597</id><published>2009-07-16T12:59:00.001-04:00</published><updated>2009-08-10T13:51:16.317-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='stackpanel'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='canvas'/><category scheme='http://www.blogger.com/atom/ns#' term='grid'/><category scheme='http://www.blogger.com/atom/ns#' term='Expression Blend'/><title type='text'>Autosizing of Grids, Canvasses and StackPanels</title><content type='html'>Deb:  Moving from a relatively static environment, like Photoshop, to a dynamic environment like Silverlight/Blend, requires learning about autosizing and how visuals will behave when the browser is resized. One of the most challenging things for me to learn was the differences in behaviors between grids, canvasses and stackpanels.&lt;br /&gt;&lt;br /&gt;I started with grids, the workhorse of the layout panels, and I got comfortable with setting the height and width to 'auto', and the alignment to stretch, and setting the margins to achieve the effect I was looking for. I learned how to set column and row sizes, locking certain ones and leaving others to size dynamically as the space changed.&lt;br /&gt;&lt;br /&gt;I moved on to canvasses, learning how to place objects on the panel in a different way, but the autosizing aspect of the layout panel worked the same as the grid. I figured I had this dynamic sizing thing figured out. Then I got cocky and started sticking stackpanels into my grids, and suddenly things weren't working the way I expected. This video explains why:&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;object width="558" height="489" class="BLOG_video_class" id="BLOG_video-32c81402bd4ed6ae" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v15.nonxt7.googlevideo.com/videoplayback?id%3D32c81402bd4ed6ae%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D37A5508500D84E2140296A0824D386718064AB3B.3C1D7C70F7914C6632C2278555BDD03A93B28389%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D32c81402bd4ed6ae%26offsetms%3D5000%26itag%3Dw160%26sigh%3DfCZYoGhGDtJDARceKUjHrUbI4yw&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="558" height="489" bgcolor="#FFFFFF"flashvars="flvurl=http://v15.nonxt7.googlevideo.com/videoplayback?id%3D32c81402bd4ed6ae%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D37A5508500D84E2140296A0824D386718064AB3B.3C1D7C70F7914C6632C2278555BDD03A93B28389%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D32c81402bd4ed6ae%26offsetms%3D5000%26itag%3Dw160%26sigh%3DfCZYoGhGDtJDARceKUjHrUbI4yw&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;/p&gt;&lt;p&gt;I am not a developer, but I do have a strong intuitive understanding of hierarchies and trees. I had developed a mental model that said that if I picked 'auto' and 'stretch', my object would size to match the parent it was embedded in. Working with stackpanels forced me to reevaluate my mental model, to acknowledge that sometimes the sizing was driven by the children embedded in the object, and margins - as seen in the video - seem to be able to refer to both (in the example, the top and left margins are relative to the parent canvas but the right and bottom margins are relative to the 'children' buttons).&lt;/p&gt;&lt;p&gt;This is where trial and error has led me. If there is an explanation for these behaviors, a simplifying principle that can be applied in all cases, I would love to learn it -- I really like to understand why things are the way they are. Post a comment and let me know what you think!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-167379801424123597?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=32c81402bd4ed6ae&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/167379801424123597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=167379801424123597&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/167379801424123597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/167379801424123597'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/07/autosizing-of-grids-canvasses-and.html' title='Autosizing of Grids, Canvasses and StackPanels'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2906820626924263852</id><published>2009-07-14T12:26:00.001-04:00</published><updated>2009-08-09T12:57:52.851-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='Expression Blend'/><title type='text'>The Designer's Perspective:  Working with Silverlight and Expression Blend</title><content type='html'>Deb:  For too long now, I've been sitting on the sidelines, content to edit Steve's posts.  But it's time to start representing the designer's viewpoint when it comes to using Silverlight 3 and Expression Blend 3.&lt;br /&gt;&lt;br /&gt;I was first attracted to Silverlight for two reasons: 1) visualization is very important to me and Silverlight lets me design some very compelling visualizations, and 2) Expression Blend promised me significantly more autonomy, and the ability to do whatever I could imagine without relying on a developer to translate my vision for me.&lt;br /&gt;&lt;br /&gt;While I haven't become as autonomous as I would like, Blend keeps improving and for the most part, Blend 3 is a joy to work with.  I have my moments of frustration, sure, but they are more than offset by the power and independence I've been given.  The goal of my posts will be to reduce the frustration factor even further for fellow designers. &lt;br /&gt;&lt;br /&gt;I can summarize my attitude toward XAML by saying this:  in general, the only legitimate reason for me to go to the XAML is to finetune the sizing of rows and columns.  Other than that, I shouldn't need to even look at it.  I think this should be the ultimate test of Blend's ability to meet the needs of designers: no XAML coding required.&lt;br /&gt;&lt;br /&gt;The point of view I represent is that of someone who has graphic arts training, who is adept at Adobe tools such as Photoshop, who is an extremely heavy user of the Internet, but who knows nothing about C# or .NET.  Perhaps it may be difficult for some readers to understand someone with this background, but there are a lot of us out here.  There are many things that may be obvious to a developer that can only be painfully learned through trial and error by a designer.  Given the relative 'youth' of the Silverlight tools and their accompanying documentation (sparse), only the Internet, powerful search engines and the sharing of the Silverlight community make solving the problems we confront relatively painless.  And it always helps to know that the pain of being an early adopter of Silverlight will be compensated for by the advantages that come from being among the first to learn these skills.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2906820626924263852?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2906820626924263852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2906820626924263852&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2906820626924263852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2906820626924263852'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/07/designers-perspective-working-with.html' title='The Designer&apos;s Perspective:  Working with Silverlight and Expression Blend'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3567010350358842660</id><published>2009-07-04T21:02:00.027-04:00</published><updated>2009-07-23T10:42:42.068-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='RIA Services'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Learning RIA Services: It's Great to be a Silverlight Developer</title><content type='html'>I have built WCF integrations to SQL Server as part of building Silverlight applications. Having created the basic elements of a CRUD (Create, Read, Update, Delete) using WCF (&lt;a href="https://timheuer.com/blog/archive/2008/06/06/changes-to-accessing-services-in-silverlight-2-beta-2.aspx"&gt;see Tim Heuer's blog on how to do this&lt;/a&gt; ), I had to ask myself if there wasn't a way to achieve the same result that required less code.&lt;br /&gt;&lt;br /&gt;During MIX09 I saw Brad Adams' talks on .NET RIA Services (watch &lt;a href="http://blogs.msdn.com/brada/archive/2009/03/19/what-is-net-ria-services.aspx"&gt;Brad Adams talk&lt;/a&gt;). On 3 separate occasions I worked through these examples until I began to understand how all the parts fit together. My basic feeling was that although these services are very powerful, they made a lot of assumptions about how I wanted to collect and consume the data. Too much magic going on behind the scenes for my purposes. Using the beta release of RIA Services, according to all the demos I could find on line, there was no way to loop through the returned records without binding it to the control.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Problem Statement &lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;I wanted to find out what I was doing wrong. Is there a way to just loop over the records returned from RIA services without binding to a control? I asked the question on Stack Overflow and in the Silverlight forums.&lt;br /&gt;&lt;br /&gt;&lt;object width="620" height="525" class="BLOG_video_class" id="BLOG_video-5124cae5c8cac9ce" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v1.nonxt1.googlevideo.com/videoplayback?id%3D5124cae5c8cac9ce%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D1711BB1A8638C2360AD6B61DE245F5E03625DC70.4FC327E656317BE556E28B788C92E4F4558C01CE%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D5124cae5c8cac9ce%26offsetms%3D5000%26itag%3Dw160%26sigh%3DFAgNIv5KRoPnbJ53xYOZc8565Hs&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="620" height="525" bgcolor="#FFFFFF"flashvars="flvurl=http://v1.nonxt1.googlevideo.com/videoplayback?id%3D5124cae5c8cac9ce%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D1711BB1A8638C2360AD6B61DE245F5E03625DC70.4FC327E656317BE556E28B788C92E4F4558C01CE%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D5124cae5c8cac9ce%26offsetms%3D5000%26itag%3Dw160%26sigh%3DFAgNIv5KRoPnbJ53xYOZc8565Hs&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Community to the Rescue&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;If I knew the answer, I would have asked a better question. Isn't that always the case? The members of the developer community offered answers to my ill-formed question:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_x0fXcQg3teU/Slp3qH4xeDI/AAAAAAAAACg/hXdThGUsPS8/s1600-h/TheHelp.png"&gt;&lt;img style="WIDTH: 405px; HEIGHT: 402px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5357726272266008626" border="0" alt="" src="http://2.bp.blogspot.com/_x0fXcQg3teU/Slp3qH4xeDI/AAAAAAAAACg/hXdThGUsPS8/s400/TheHelp.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;No one gave me the exact answer. There was no code provided that I could just cut and paste, but I got great response in hours and their insight led me to the answer I was looking for:&lt;br /&gt;&lt;br /&gt;&lt;object width="620" height="525" class="BLOG_video_class" id="BLOG_video-884bebb59b842eb4" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v17.nonxt1.googlevideo.com/videoplayback?id%3D884bebb59b842eb4%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D17609D1D9060A3404554C1771431B9FDB12CCD0C.3B6BEA389903B91BB0B8B1A273538FC419890B34%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D884bebb59b842eb4%26offsetms%3D5000%26itag%3Dw160%26sigh%3DZdxhscNBxkdFXIjtBEMf1S7KmKU&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="620" height="525" bgcolor="#FFFFFF"flashvars="flvurl=http://v17.nonxt1.googlevideo.com/videoplayback?id%3D884bebb59b842eb4%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D17609D1D9060A3404554C1771431B9FDB12CCD0C.3B6BEA389903B91BB0B8B1A273538FC419890B34%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D884bebb59b842eb4%26offsetms%3D5000%26itag%3Dw160%26sigh%3DZdxhscNBxkdFXIjtBEMf1S7KmKU&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Not long after I starting working on this problem, Silverlight 3 was released. RIA services have changed and I have not had time to investigate, but once I do I will add a new post.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;It is Great to be a Silverlight Developer&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I have been writing software since I was 18; I would have started sooner if I had access to a computer. Looking back over my 30+ years of programming, I am now having more fun than ever, and I think it is because of the times we live in -- Silverlight, the Internet, and the community of people who use them both. Silverlight has turned web applications into a rich and now, with OOB, sometimes even unconnected experience. Today's development culture is one of generosity and sharing. I am in contact with people around the world, Silverlight gurus and novices alike, and they all love to share. You get the sense that we are all looking to see how much we can accomplish together with Silverlight.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3567010350358842660?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3567010350358842660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3567010350358842660&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3567010350358842660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3567010350358842660'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/07/learning-ria-services-its-great-to-be.html' title='Learning RIA Services: It&apos;s Great to be a Silverlight Developer'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_x0fXcQg3teU/Slp3qH4xeDI/AAAAAAAAACg/hXdThGUsPS8/s72-c/TheHelp.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3579888245373711536</id><published>2009-07-03T20:52:00.019-04:00</published><updated>2009-07-10T04:58:29.700-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><title type='text'>Bing Maps Silverlight Control Part 5: Calculating Distance</title><content type='html'>My dad was the first person to show me how to measure distances on a map using a pair of dividers and the scale printed on the map key. There is a much better way to do this using the Bing Maps Silverlight control -- it just takes a little programming and finding the right equation.&lt;br /&gt;&lt;br /&gt;&lt;object width="586" height="427" class="BLOG_video_class" id="BLOG_video-56213c54d19a8faa" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v13.nonxt4.googlevideo.com/videoplayback?id%3D56213c54d19a8faa%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D174217E9751B5B932A28603ED82DB789C0048E4C.5C5D0724E731BF253737DFC3D5D50DC3557EEF3D%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D56213c54d19a8faa%26offsetms%3D5000%26itag%3Dw160%26sigh%3DQy9NbvLrxVpMnYSkrehlaJ4BnbA&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="586" height="427" bgcolor="#FFFFFF"flashvars="flvurl=http://v13.nonxt4.googlevideo.com/videoplayback?id%3D56213c54d19a8faa%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D174217E9751B5B932A28603ED82DB789C0048E4C.5C5D0724E731BF253737DFC3D5D50DC3557EEF3D%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D56213c54d19a8faa%26offsetms%3D5000%26itag%3Dw160%26sigh%3DQy9NbvLrxVpMnYSkrehlaJ4BnbA&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Here is the Bobcat Video I told you about:&lt;br /&gt;&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/A7WapnRGGn4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/A7WapnRGGn4&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Back to Programming...&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Here is how you calculate the distance between points on the earth.  You also need to know EarthRadiusInMiles = 3956.0;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt; &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Calculate the distance between two geocodes. Defaults to using Miles. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt; &lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; CalcDistance(&lt;span class="kwrd"&gt;double&lt;/span&gt; lat1, &lt;span class="kwrd"&gt;double&lt;/span&gt; lng1, &lt;span class="kwrd"&gt;double&lt;/span&gt; lat2, &lt;span class="kwrd"&gt;double&lt;/span&gt; lng2)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; CalcDistance(lat1, lng1, lat2, lng2, GeoCodeCalcMeasurement.Miles);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt; &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// Calculate the distance between two geocodes. &lt;/span&gt;&lt;br /&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt; &lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; CalcDistance(&lt;span class="kwrd"&gt;double&lt;/span&gt; lat1, &lt;span class="kwrd"&gt;double&lt;/span&gt; lng1, &lt;span class="kwrd"&gt;double&lt;/span&gt; lat2, &lt;span class="kwrd"&gt;double&lt;/span&gt; lng2, GeoCodeCalcMeasurement m)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;double&lt;/span&gt; radius = GeoCodeCalc.EarthRadiusInMiles;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (m == GeoCodeCalcMeasurement.Kilometers) { radius = GeoCodeCalc.EarthRadiusInKilometers; }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; radius * 2 * Math.Asin(Math.Min(1, Math.Sqrt((Math.Pow(Math.Sin((DiffRadian(lat1, lat2)) / 2.0), 2.0) + Math.Cos(ToRadian(lat1)) * Math.Cos(ToRadian(lat2)) * Math.Pow(Math.Sin((DiffRadian(lng1, lng2)) / 2.0), 2.0)))));&lt;br /&gt;        }&lt;/pre&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;I created a Marker class to mark the end points of the distance calculation. To show the user that they are in distance calculation mode, I have also changed the cursor on the map control. In this case, I alternate between the arrow and the pointing finger.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        PointsOfInterest m_oMarkers = &lt;span class="kwrd"&gt;new&lt;/span&gt; PointsOfInterest();&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; cbMeasure_Checked(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            Map1.Cursor = Cursors.Hand;&lt;br /&gt;            m_oMarkers.Clear();&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; cbMeasure_Unchecked(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            Map1.Cursor = Cursors.Arrow;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; ( m_oMarkers.Count &amp;gt; 1 )&lt;br /&gt;                AddLine(m_oMarkers,.5);&lt;br /&gt;        }&lt;/pre&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;The code for collecting the user's selection of points is here:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; Map1_MouseClick(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, MapMouseEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            var oLocation = Map1.ViewportPointToLocation(e.ViewportPoint);&lt;br /&gt;&lt;br /&gt;            PointOfInterest oPOI = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (cbMeasure.IsChecked == &lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                oPOI = &lt;span class="kwrd"&gt;new&lt;/span&gt; Marker() { Loc = oLocation };&lt;br /&gt;                m_oMarkers.Add(oPOI);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                oPOI = &lt;span class="kwrd"&gt;new&lt;/span&gt; PointOfInterest() { Loc = oLocation };&lt;br /&gt;                m_oList.Add(oPOI);&lt;br /&gt;            }&lt;br /&gt;           &lt;br /&gt;            RenderPoint(oPOI);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (cbDraw.IsChecked == &lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br /&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;double&lt;/span&gt; dRadius = &lt;span class="kwrd"&gt;double&lt;/span&gt;.Parse(txtRadius.Text);&lt;br /&gt;                    AddCircle(oLocation, dRadius, .5);&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt;( Exception ex)&lt;br /&gt;                {&lt;br /&gt;                    MessageBox.Show(ex.Message);&lt;br /&gt;                }&lt;br /&gt;        }&lt;/pre&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;Using a polyline and a tool tip is great way to report the distance:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;       &lt;span class="kwrd"&gt;double&lt;/span&gt; DistanceInMiles(LocationCollection oLocs)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;double&lt;/span&gt; dDistance = 0.0;&lt;br /&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; oLocs.Count() - 1; i++)&lt;br /&gt;                dDistance += DistanceInMiles(oLocs[i], oLocs[i + 1]);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; dDistance;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;double&lt;/span&gt; DistanceInMiles(Location Loc1, Location Loc2)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;double&lt;/span&gt; dMiles = GeoCodeCalc.CalcDistance(Loc1.Latitude, Loc1.Longitude, Loc2.Latitude, Loc2.Longitude);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; dMiles;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        LocationCollection RenderLine(List&amp;lt;PointOfInterest&amp;gt; oList)&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            var oPOIs = (from oPOI &lt;span class="kwrd"&gt;in&lt;/span&gt; oList&lt;br /&gt;                         &lt;span class="kwrd"&gt;where&lt;/span&gt; oPOI &lt;span class="kwrd"&gt;is&lt;/span&gt; Marker&lt;br /&gt;                         select oPOI).ToList&amp;lt;PointOfInterest&amp;gt;();&lt;br /&gt;&lt;br /&gt;            var oLocs = &lt;span class="kwrd"&gt;new&lt;/span&gt; LocationCollection();&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var oPOI &lt;span class="kwrd"&gt;in&lt;/span&gt; oPOIs)&lt;br /&gt;                oLocs.Add(oPOI.Loc);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oLocs;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; AddLine(List&amp;lt;PointOfInterest&amp;gt; oList, &lt;span class="kwrd"&gt;double&lt;/span&gt; dOpacity)&lt;br /&gt;        {&lt;br /&gt;            MapPolyline polyline = &lt;span class="kwrd"&gt;new&lt;/span&gt; MapPolyline();&lt;br /&gt;            polyline.Stroke = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Red);&lt;br /&gt;            polyline.StrokeThickness = 1;&lt;br /&gt;            polyline.Opacity = dOpacity;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//this works in miles&lt;/span&gt;&lt;br /&gt;            LocationCollection oLocs = RenderLine(oList);&lt;br /&gt;            polyline.Locations = oLocs;&lt;br /&gt;            Map1.AddChild(polyline);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;double&lt;/span&gt; dDist = DistanceInMiles(oLocs);&lt;br /&gt;&lt;br /&gt;            ToolTipService.SetToolTip(polyline, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"{0:0.0} mi \n {1:0.00} yd"&lt;/span&gt;, dDist, dDist * 5280.0 / 3.0));&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3579888245373711536?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3579888245373711536/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3579888245373711536&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3579888245373711536'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3579888245373711536'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/07/bing-maps-silverlight-control-part-5.html' title='Bing Maps Silverlight Control Part 5: Calculating Distance'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3319835435241361333</id><published>2009-06-22T21:41:00.003-04:00</published><updated>2009-06-24T09:21:41.335-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><title type='text'>Virtual Earth Rebranded to Bing Maps</title><content type='html'>We've been doing a series of posts on Silverlight 3 and Virtual Earth. &lt;br /&gt;&lt;br /&gt;Microsoft has recently rebranded Virtual Earth, renaming it "Bing Maps".  Read about their thinking here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.bing.com/community/blogs/maps/archive/2009/05/28/rebranding-microsoft-virtual-earth-to.aspx"&gt;http://www.bing.com/community/blogs/maps/archive/2009/05/28/rebranding-microsoft-virtual-earth-to.aspx&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3319835435241361333?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3319835435241361333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3319835435241361333&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3319835435241361333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3319835435241361333'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/06/virtual-earth-rebranded-to-bing-maps.html' title='Virtual Earth Rebranded to Bing Maps'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-5165188547129735805</id><published>2009-06-21T12:37:00.007-04:00</published><updated>2009-06-24T09:17:00.679-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><title type='text'>Bing Maps Silverlight Control Part 4: Drawing Circles To Scale</title><content type='html'>When you add scaled geometry to the Virtual Earth application you need to remember 2 things:&lt;br /&gt;&lt;br /&gt;1) The earth is not flat, so your math needs to account for the curvature of the earth.&lt;br /&gt;&lt;br /&gt;2) The Virtual Earth API has, among other things, MapPolygon objects, which are treated as scaled geometry. In my example, I wanted to draw a circle around a point that showed what was on the map 10 miles in any direction. This video shows my reasons why:&lt;br /&gt;&lt;br /&gt;&lt;object width="398" height="393" class="BLOG_video_class" id="BLOG_video-502d51f01b90c7c8" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v17.nonxt2.googlevideo.com/videoplayback?id%3D502d51f01b90c7c8%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D1992ECFB91CC0BCF0A00A5DD6A7BCAAC677E978.AD4431AD0A930FBDA52AA087FCED48B96F281FF%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D502d51f01b90c7c8%26offsetms%3D5000%26itag%3Dw160%26sigh%3DiKK8UlCvVLbItMeiGOJUGUYPOxg&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="398" height="393" bgcolor="#FFFFFF"flashvars="flvurl=http://v17.nonxt2.googlevideo.com/videoplayback?id%3D502d51f01b90c7c8%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D1992ECFB91CC0BCF0A00A5DD6A7BCAAC677E978.AD4431AD0A930FBDA52AA087FCED48B96F281FF%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D502d51f01b90c7c8%26offsetms%3D5000%26itag%3Dw160%26sigh%3DiKK8UlCvVLbItMeiGOJUGUYPOxg&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I pulled all the parts to build this application from the web. You can find the formulas to calculate distances on a curved surface in Wikipedia: &lt;a href="http://en.wikipedia.org/wiki/Great-circle_distance" target="_blank"&gt;Great Circle Distance&lt;/a&gt;&lt;br /&gt;Tim Heuer had a post on calculating the points in a circle using Java: &lt;a href="http://timheuer.com/blog/archive/2007/02/21/13996.aspx" target="_blank"&gt;Drawing a Radius&lt;/a&gt;&lt;br /&gt;In my project I converted all the code to C# and separated the calculation of locations and the generation of a MapPolygon into two functions.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; AddCircle(Location oLoc, &lt;span class="kwrd"&gt;double&lt;/span&gt; dRadius, &lt;span class="kwrd"&gt;double&lt;/span&gt; dOpacity)&lt;br /&gt;        {&lt;br /&gt;            MapPolygon polygon = &lt;span class="kwrd"&gt;new&lt;/span&gt; MapPolygon();&lt;br /&gt;            polygon.Fill = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Green);&lt;br /&gt;            polygon.Stroke = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Blue);&lt;br /&gt;            polygon.StrokeThickness = 5;&lt;br /&gt;            polygon.Opacity = dOpacity;&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//this works in miles&lt;/span&gt;&lt;br /&gt;            polygon.Locations = DrawACircle(oLoc, dRadius);&lt;br /&gt;            Map1.AddChild(polygon);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; LocationCollection DrawACircle(Location oLoc, &lt;span class="kwrd"&gt;double&lt;/span&gt; dRadius)&lt;br /&gt;        {&lt;br /&gt;            var oLocs = &lt;span class="kwrd"&gt;new&lt;/span&gt; LocationCollection();&lt;br /&gt;&lt;br /&gt;            var earthRadius = GeoCodeCalc.EarthRadiusInMiles;&lt;br /&gt;            var lat = GeoCodeCalc.ToRadian(oLoc.Latitude); &lt;span class="rem"&gt;//radians &lt;/span&gt;&lt;br /&gt;            var lon = GeoCodeCalc.ToRadian(oLoc.Longitude); &lt;span class="rem"&gt;//radians &lt;/span&gt;&lt;br /&gt;            var d = dRadius / earthRadius; &lt;span class="rem"&gt;// d = angular distance covered on earths surface &lt;/span&gt;&lt;br /&gt;         &lt;br /&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; x = 0; x&amp;lt;= 360; x++)&lt;br /&gt;            {&lt;br /&gt;                var brng = GeoCodeCalc.ToRadian(x); &lt;span class="rem"&gt;//radians &lt;/span&gt;&lt;br /&gt;                var latRadians = Math.Asin(Math.Sin(lat) * Math.Cos(d) + Math.Cos(lat) * Math.Sin(d) * Math.Cos(brng));&lt;br /&gt;                var lngRadians = lon + Math.Atan2(Math.Sin(brng) * Math.Sin(d) * Math.Cos(lat), Math.Cos(d) - Math.Sin(lat) * Math.Sin(latRadians));&lt;br /&gt;&lt;br /&gt;                var pt = &lt;span class="kwrd"&gt;new&lt;/span&gt; Location(180.0 * latRadians / Math.PI, 180.0 * lngRadians / Math.PI);&lt;br /&gt;                oLocs.Add(pt);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oLocs;&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&lt;br /&gt;{&lt;br /&gt; font-size: small;&lt;br /&gt; color: black;&lt;br /&gt; font-family: Consolas, "Courier New", Courier, Monospace;&lt;br /&gt; background-color: #ffffff;&lt;br /&gt; /*white-space: pre;*/&lt;br /&gt;}&lt;br /&gt;.csharpcode pre { margin: 0em; }&lt;br /&gt;.csharpcode .rem { color: #008000; }&lt;br /&gt;.csharpcode .kwrd { color: #0000ff; }&lt;br /&gt;.csharpcode .str { color: #006080; }&lt;br /&gt;.csharpcode .op { color: #0000c0; }&lt;br /&gt;.csharpcode .preproc { color: #cc6633; }&lt;br /&gt;.csharpcode .asp { background-color: #ffff00; }&lt;br /&gt;.csharpcode .html { color: #800000; }&lt;br /&gt;.csharpcode .attr { color: #ff0000; }&lt;br /&gt;.csharpcode .alt&lt;br /&gt;{&lt;br /&gt; background-color: #f4f4f4;&lt;br /&gt; width: 100%;&lt;br /&gt; margin: 0em;&lt;br /&gt;}&lt;br /&gt;.csharpcode .lnum { color: #606060; }&lt;br /&gt;&lt;/style&gt;&lt;br /&gt;Integrating this with the current UI was straight-forward -- I just added a little more code to the actions the application was already doing. So drawing circles around the current location became this:&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;span style="font-family:Georgia;"&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; btnCircle_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            var oMyLoc = from oItem &lt;span class="kwrd"&gt;in&lt;/span&gt; m_oList&lt;br /&gt;                         &lt;span class="kwrd"&gt;where&lt;/span&gt; oItem &lt;span class="kwrd"&gt;is&lt;/span&gt; MyLocation&lt;br /&gt;                         select oItem;&lt;br /&gt;&lt;br /&gt;            PointOfInterest oWhereIAm = oMyLoc.First&amp;lt;PointOfInterest&amp;gt;();&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oWhereIAm == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                MessageBox.Show(&lt;span class="str"&gt;"Add Where Am I to the Map"&lt;/span&gt;);&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 1; i &amp;lt;= 5; i++)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;double&lt;/span&gt; dRadius = i * 10.0;&lt;br /&gt;                AddCircle(oWhereIAm.Loc, dRadius, .15);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And drawing a circle of a given radius about any mouse click became this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; Map1_MouseClick(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, MapMouseEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            var oLocation = Map1.ViewportPointToLocation(e.ViewportPoint);&lt;br /&gt;&lt;br /&gt;            var oPOI = &lt;span class="kwrd"&gt;new&lt;/span&gt; PointOfInterest() { Loc = oLocation };&lt;br /&gt;            m_oList.Add(oPOI);&lt;br /&gt;&lt;br /&gt;            RenderPoint(oPOI);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (cbDraw.IsChecked == &lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br /&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;double&lt;/span&gt; dRadius = &lt;span class="kwrd"&gt;double&lt;/span&gt;.Parse(txtRadius.Text);&lt;br /&gt;                    AddCircle(oPOI.Loc, dRadius, .5);&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt;( Exception ex)&lt;br /&gt;                {&lt;br /&gt;                    MessageBox.Show(ex.Message);&lt;br /&gt;                }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the next post I will show how to measure between two user-selected points.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-5165188547129735805?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/5165188547129735805/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=5165188547129735805&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5165188547129735805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5165188547129735805'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/06/bing-live-maps-silverlight-control-part.html' title='Bing Maps Silverlight Control Part 4: Drawing Circles To Scale'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-8906063111577990249</id><published>2009-06-16T17:01:00.009-04:00</published><updated>2009-06-24T09:16:34.003-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><category scheme='http://www.blogger.com/atom/ns#' term='Best Buy'/><title type='text'>Virtual Earth Silverlight Control Part 3: Locating Best Buy Stores</title><content type='html'>I was searching the web for sources of Lat/Long data I could mash-up to in a Virtual Earth application and I ran across &lt;a href="http://remix.bestbuy.com/"&gt;Best Buy ReMix&lt;/a&gt;. The API to collect store location information was easy to use and returned Lat/Long info, so I integrated it into the application. Watch this video to see how I did it:&lt;br /&gt;&lt;br /&gt;&lt;object width="548" height="421" class="BLOG_video_class" id="BLOG_video-71eb8f120998104c" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v19.nonxt4.googlevideo.com/videoplayback?id%3D71eb8f120998104c%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D296148B025AAB200A016C9DF89730A66E4968311.CBD6C8876E09C13B09964145203EDF2215E00D7%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D71eb8f120998104c%26offsetms%3D5000%26itag%3Dw160%26sigh%3DQd58zQFh01fioEzTNbNQ2wcr9UA&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="548" height="421" bgcolor="#FFFFFF"flashvars="flvurl=http://v19.nonxt4.googlevideo.com/videoplayback?id%3D71eb8f120998104c%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D296148B025AAB200A016C9DF89730A66E4968311.CBD6C8876E09C13B09964145203EDF2215E00D7%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D71eb8f120998104c%26offsetms%3D5000%26itag%3Dw160%26sigh%3DQd58zQFh01fioEzTNbNQ2wcr9UA&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I like to start by testing the URL in the browser:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;http://api.remix.bestbuy.com/v1/stores(area(44236,20))?apiKey=[YourKey] &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The Remix API returned XML describing the stores within 20 miles of my zipcode. Here is some of what I got back:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&amp;lt;stores currentPage=&lt;span class="str"&gt;"1"&lt;/span&gt; totalPages=&lt;span class="str"&gt;"1"&lt;/span&gt; from=&lt;span class="str"&gt;"1"&lt;/span&gt; to=&lt;span class="str"&gt;"6"&lt;/span&gt; total=&lt;span class="str"&gt;"6"&lt;/span&gt; queryTime=&lt;span class="str"&gt;"0.004"&lt;/span&gt; totalTime=&lt;span class="str"&gt;"0.013"&lt;/span&gt; canonicalUrl=&lt;span class="str"&gt;"/v1/stores(area("&lt;/span&gt;44236&lt;span class="str"&gt;",20))?apiKey=fbsn9dsqvgnm42vyk4x5hman"&lt;/span&gt;&amp;gt;&lt;br /&gt;  &amp;lt;store&amp;gt;&lt;br /&gt;    &amp;lt;storeId&amp;gt;758&amp;lt;/storeId&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;Macedonia OH&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;address&amp;gt;470 East Aurora Road&amp;lt;/address&amp;gt;&lt;br /&gt;    &amp;lt;city&amp;gt;Macedonia&amp;lt;/city&amp;gt;&lt;br /&gt;    &amp;lt;region&amp;gt;OH&amp;lt;/region&amp;gt;&lt;br /&gt;    &amp;lt;postalCode&amp;gt;44056&amp;lt;/postalCode&amp;gt;&lt;br /&gt;    &amp;lt;fullPostalCode&amp;gt;44056-1834&amp;lt;/fullPostalCode&amp;gt;&lt;br /&gt;    &amp;lt;country&amp;gt;US&amp;lt;/country&amp;gt;&lt;br /&gt;    &amp;lt;lat&amp;gt;41.313461&amp;lt;/lat&amp;gt;&lt;br /&gt;    &amp;lt;lng&amp;gt;-81.521233&amp;lt;/lng&amp;gt;&lt;br /&gt;    &amp;lt;phone&amp;gt;330-468-6850&amp;lt;/phone&amp;gt;&lt;br /&gt;    &amp;lt;hours&amp;gt;10:00am - 9:00pm Monday - Friday, 11:00am - 6:00pm Saturday, 11:00am - 6:00pm Sunday&amp;lt;/hours&amp;gt;&lt;br /&gt;    &amp;lt;distance&amp;gt;6.0&amp;lt;/distance&amp;gt;&lt;br /&gt;  &amp;lt;/store&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The next step is to verify that Silverlight can consume this data using the WebClient Class. The code is simple but it does not always work, based on permissions (&lt;a href="http://timheuer.com/blog/archive/2008/04/06/silverlight-cross-domain-policy-file-snippet-intellisense.aspx"&gt;see Tim Heuer's explanation of this&lt;/a&gt;). I test it with this code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; LoadBestBuyStores()&lt;br /&gt;        {&lt;br /&gt;            WebClient oClient = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebClient();&lt;br /&gt;   &lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sUri = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"http://api.remix.bestbuy.com/v1/stores(area({0},20))?apiKey=fbsn9dsqvgnm42vyk4x5hman"&lt;/span&gt;, txtZipCode.Text);&lt;br /&gt;            var oAddress = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(sUri);&lt;br /&gt;            oClient.DownloadStringCompleted += &lt;span class="kwrd"&gt;new&lt;/span&gt; DownloadStringCompletedEventHandler(BestBuyStores_DownloadStringCompleted);&lt;br /&gt;            oClient.DownloadStringAsync(oAddress);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; BestBuyStores_DownloadStringCompleted(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, DownloadStringCompletedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sResult = e.Result;&lt;br /&gt;            MessageBox.Show(sResult);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To finish the application, I needed to parse the XML that was returned and map it into an object instance, so I defined a class 'BestBuyStores':&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BestBuyStore : PointOfInterest&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Address { get; set; }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; City { get; set; }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Region { get; set; }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Phone { get; set; }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Hours { get; set; }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and then added LinqToXML code to build my objects:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; BestBuyStores_DownloadStringCompleted(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, DownloadStringCompletedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (e.Error != &lt;span class="kwrd"&gt;null&lt;/span&gt; )&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sResult = e.Result;&lt;br /&gt;&lt;br /&gt;            var doc = XDocument.Parse(sResult);&lt;br /&gt;&lt;br /&gt;            var oStores = from element &lt;span class="kwrd"&gt;in&lt;/span&gt; doc.Descendants(&lt;span class="str"&gt;"store"&lt;/span&gt;)&lt;br /&gt;                            select &lt;span class="kwrd"&gt;new&lt;/span&gt; BestBuyStore&lt;br /&gt;                            {&lt;br /&gt;                                Name = element.Element(&lt;span class="str"&gt;"name"&lt;/span&gt;).Value,&lt;br /&gt;                                Address = element.Element(&lt;span class="str"&gt;"address"&lt;/span&gt;).Value,&lt;br /&gt;                                City = element.Element(&lt;span class="str"&gt;"city"&lt;/span&gt;).Value,&lt;br /&gt;                                Region = element.Element(&lt;span class="str"&gt;"region"&lt;/span&gt;).Value,&lt;br /&gt;                                Phone = element.Element(&lt;span class="str"&gt;"phone"&lt;/span&gt;).Value,&lt;br /&gt;                                Hours = element.Element(&lt;span class="str"&gt;"hours"&lt;/span&gt;).Value,&lt;br /&gt;                                Loc = &lt;span class="kwrd"&gt;new&lt;/span&gt; Location(&lt;span class="kwrd"&gt;double&lt;/span&gt;.Parse(element.Element(&lt;span class="str"&gt;"lat"&lt;/span&gt;).Value), &lt;span class="kwrd"&gt;double&lt;/span&gt;.Parse(element.Element(&lt;span class="str"&gt;"lng"&lt;/span&gt;).Value))&lt;br /&gt;                            };&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (BestBuyStore oStore &lt;span class="kwrd"&gt;in&lt;/span&gt; oStores.ToList&amp;lt;BestBuyStore&amp;gt;())&lt;br /&gt;            {&lt;br /&gt;                RenderPoint(oStore);&lt;br /&gt;                m_oList.Add(oStore);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            frmBestBuy.Visibility = Visibility.Visible;&lt;br /&gt;            frmBestBuy.ItemsSource = oStores;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally by extending the RenderPoint method I was able to mark each location with a custom Best Buy graphic:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; RenderPoint(PointOfInterest oPOI)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oPOI &lt;span class="kwrd"&gt;is&lt;/span&gt; MyLocation)&lt;br /&gt;            {&lt;br /&gt;                Uri oSource = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(&lt;span class="str"&gt;@"Pushpin.png"&lt;/span&gt;, UriKind.Relative);&lt;br /&gt;                var oBitmap = &lt;span class="kwrd"&gt;new&lt;/span&gt; BitmapImage(oSource);&lt;br /&gt;                var oImage = &lt;span class="kwrd"&gt;new&lt;/span&gt; Image() { Source = oBitmap, Width=23, Height=27 };&lt;br /&gt;                m_oLayer.AddChild(oImage, oPOI.Loc, PositionMethod.BottomCenter);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (oPOI &lt;span class="kwrd"&gt;is&lt;/span&gt; BestBuyStore)&lt;br /&gt;            {&lt;br /&gt;                Uri oSource = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(&lt;span class="str"&gt;@"BestBuy.png"&lt;/span&gt;, UriKind.Relative);&lt;br /&gt;                var oBitmap = &lt;span class="kwrd"&gt;new&lt;/span&gt; BitmapImage(oSource);&lt;br /&gt;                var oImage = &lt;span class="kwrd"&gt;new&lt;/span&gt; Image() { Source = oBitmap, Width = 23, Height = 27 };&lt;br /&gt;                m_oLayer.AddChild(oImage, oPOI.Loc, PositionMethod.BottomLeft);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                var oRect = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Windows.Shapes.Rectangle() { Fill = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Red), Width = 10, Height = 10 };&lt;br /&gt;                m_oLayer.AddChild(oRect, oPOI.Loc, PositionMethod.Center);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-8906063111577990249?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/8906063111577990249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=8906063111577990249&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8906063111577990249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8906063111577990249'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/06/virtual-earth-silverlight-control-part_16.html' title='Virtual Earth Silverlight Control Part 3: Locating Best Buy Stores'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-4105755604935749780</id><published>2009-06-09T17:57:00.005-04:00</published><updated>2009-06-24T09:16:34.004-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Generic Conversion'/><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><title type='text'>Generic Type Conversion</title><content type='html'>While working on the Virtual Earth map application, I discovered the need to parse data from a string of characters. So I searched the net and found this answer on stack overflow: &lt;a href="http://stackoverflow.com/questions/8625/generic-type-conversion-from-string" target="_blank"&gt;generic-type-conversion-from-string&lt;/a&gt; . I like this code example because it looks like the simplest and most general approach: &lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TypedProperty&amp;lt;T&amp;gt; : Property&lt;br /&gt;{&lt;br /&gt;     &lt;span class="kwrd"&gt;public&lt;/span&gt; T TypedValue&lt;br /&gt;     {&lt;br /&gt;        get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (T)Convert.ChangeType(&lt;span class="kwrd"&gt;base&lt;/span&gt;.Value, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(T)); }&lt;br /&gt;        set { &lt;span class="kwrd"&gt;base&lt;/span&gt;.Value = &lt;span class="kwrd"&gt;value&lt;/span&gt;.ToString();}&lt;br /&gt;     }&lt;br /&gt;}&lt;/pre&gt;But if you cut and paste the code into a Silverlight 2 or Silverlight 3 application it does not run. This is because the two argument version of the ChangeType method is not part of the Silverlight runtime. I guess I could have used the three argument version, but instead I implemented a function the uses reflection:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; TryParse&amp;lt;T&amp;gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt; sValue, &lt;span class="kwrd"&gt;out&lt;/span&gt; T oValue) &lt;span class="kwrd"&gt;where&lt;/span&gt; T : IConvertible&lt;br /&gt;{&lt;br /&gt;     oValue = &lt;span class="kwrd"&gt;default&lt;/span&gt;(T);&lt;br /&gt;&lt;br /&gt;     &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;     {&lt;br /&gt;          &lt;span class="kwrd"&gt;string&lt;/span&gt;[] parts = sValue.Split(&lt;span class="str"&gt;':'&lt;/span&gt;);&lt;br /&gt;          MethodInfo oMethod = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(T).GetMethod(&lt;span class="str"&gt;"Parse"&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; Type[] { &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;string&lt;/span&gt;) } );&lt;br /&gt;          oValue = (T)oMethod.Invoke(&lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { parts[1].Trim() });&lt;br /&gt;          &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;br /&gt;     }&lt;br /&gt;     &lt;span class="kwrd"&gt;catch&lt;/span&gt; { }&lt;br /&gt;     &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;}&lt;/pre&gt;&lt;strong&gt;Silverlight Size vs. Functionality&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;You find this all the time in Silverlight development -- some of the tools, functions and features you have come to rely on in .NET are just not part of the lightweight Silverlight runtime. I read on one blog that programming with Silverlight is like going camping with .NET. In fact, I first learned this the hard way trying to recompile some previous .NET code. I couldn't include the existing library -- it had to be rebuilt using the Silverlight libraries. When I attempted to recompile it, I found that it needed to be reengineered to use functionality available in the Silverlight runtime.&lt;br /&gt;&lt;br /&gt;I have always been able to find a creative solution to simple programming issues like the one above, and I think the ability to deliver my solution over the web to any machine, without creating a custom install, makes it worth the effort to find these alternative approaches.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-4105755604935749780?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/4105755604935749780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=4105755604935749780&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/4105755604935749780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/4105755604935749780'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/06/generic-type-conversion.html' title='Generic Type Conversion'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3375194943770563371</id><published>2009-06-07T21:56:00.020-04:00</published><updated>2009-06-24T09:16:34.004-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><title type='text'>Virtual Earth Silverlight Control Part 2:  Locate Me</title><content type='html'>It was a post by Nikhil Kothari that inspired me to create a method to report my current location on the Virtual Earth Silverlight control.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nikhilk.net/Silverlight-Locate-Me.aspx"&gt;http://www.nikhilk.net/Silverlight-Locate-Me.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;While I was traveling around the country (see &lt;a href="http://www.wiredwalkabout.com/"&gt;http://www.wiredwalkabout.com/&lt;/a&gt;), I would run Nikhil's application to see the result. For the most part, it always reported my location about 20 miles from where I really was, which I think is a problem with the web service used and not the code calling it.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://api.hostip.info/get_html.php?position=true"&gt;http://api.hostip.info/get_html.php?position=true&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_x0fXcQg3teU/Si1W_ILyKOI/AAAAAAAAACY/ST25ux7hEWg/s1600-h/LocateMeInAkron.png"&gt;&lt;img style="WIDTH: 400px; HEIGHT: 327px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5345023975287302370" border="0" alt="" src="http://2.bp.blogspot.com/_x0fXcQg3teU/Si1W_ILyKOI/AAAAAAAAACY/ST25ux7hEWg/s400/LocateMeInAkron.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nikhil's current live sample has been updated, but it is still not at good as a GPS. The application source code is worth looking at in detail. He uses techniques that are more advanced than calling WebClient, and as a programmer it is interesting to know how to do same thing many different ways (viewing this link requires you have Silverlight 3 installed):&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nikhilk.net/Content/Posts/SilverlightLocateMe/LocateMe.htm"&gt;http://www.nikhilk.net/Content/Posts/SilverlightLocateMe/LocateMe.htm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This post is about integrating this functionality into the mapping application I am currently developing. I have decided to create a separate class of objects to mark my current location. I did this mainly because I wanted to use a different symbol to mark myself on the map -- like a "You Are Here" marker. I have extended this class to collect a time stamp, and this -- in combination with persistence -- can be used to track my movements.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyLocation : PointOfInterest&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime TimeStamp { get; set; }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; MyLocation()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            : &lt;span class="kwrd"&gt;base&lt;/span&gt;()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            TimeStamp = DateTime.Now;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Serializer Methods&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; XElement PersistTo(ModelSerializer oSerializer, XElement oSelf)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            XElement oXElement = &lt;span class="kwrd"&gt;base&lt;/span&gt;.PersistTo(oSerializer, oSelf);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            oXElement.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; XAttribute(&lt;span class="str"&gt;"TimeStamp"&lt;/span&gt;, TimeStamp.ToString()));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oXElement;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IMapModel RecoverFrom(ModelSerializer oSerializer, XElement oElement)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            var oResult = &lt;span class="kwrd"&gt;base&lt;/span&gt;.RecoverFrom(oSerializer, oElement);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sTimeStamp = oElement.Attribute(&lt;span class="str"&gt;"TimeStamp"&lt;/span&gt;).Value;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            TimeStamp = DateTime.Parse(sTimeStamp);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oResult;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    }&lt;/pre&gt;I needed to modify the rendering code in order to display a different picture for this class. With this quick change, objects of type MyLocation now show a pushpin instead of a red rectangle.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; RenderPoint(PointOfInterest oPOI)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oPOI &lt;span class="kwrd"&gt;is&lt;/span&gt; MyLocation)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                Uri oSource = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(&lt;span class="str"&gt;@"Pushpin.png"&lt;/span&gt;, UriKind.Relative);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                var oBitmap = &lt;span class="kwrd"&gt;new&lt;/span&gt; BitmapImage(oSource);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                var oImage = &lt;span class="kwrd"&gt;new&lt;/span&gt; Image() { Source = oBitmap, Width=23, Height=27 };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                m_oLayer.AddChild(oImage, oPOI.Loc, PositionMethod.BottomCenter);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// Create a Rectangle Shape to Show as the "Pushpin"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// Set it's Size to 10x10&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                var oRect = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Windows.Shapes.Rectangle() { Fill = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Red), Width = 10, Height = 10 };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="rem"&gt;// Add Rectangle to MapLayer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                m_oLayer.AddChild(oRect, oPOI.Loc, PositionMethod.Center);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;/pre&gt;The code to query the web service using WebClient follows. This is an asynchronous call that returns a string delimited by line feeds, so I used Nikhil's trick of reading from a stream to parse out and convert the Lat/Long information.&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; WhereAmI()&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            WebClient oClient = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebClient();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            var oAddress = &lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(&lt;span class="str"&gt;@"http://api.hostip.info/get_html.php?position=true"&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            oClient.DownloadStringCompleted += &lt;span class="kwrd"&gt;new&lt;/span&gt; DownloadStringCompletedEventHandler(oClient_DownloadStringCompleted);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            oClient.DownloadStringAsync(oAddress);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; oClient_DownloadStringCompleted(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, DownloadStringCompletedEventArgs e)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sResult = e.Result;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader sr = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(&lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream(Encoding.UTF8.GetBytes(sResult))))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                {&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    sr.ReadLine();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    sr.ReadLine();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;double&lt;/span&gt; lat = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    TryParse&amp;lt;Double&amp;gt;(sr.ReadLine(), &lt;span class="kwrd"&gt;out&lt;/span&gt; lat);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;double&lt;/span&gt; lng = 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    TryParse&amp;lt;Double&amp;gt;(sr.ReadLine(), &lt;span class="kwrd"&gt;out&lt;/span&gt; lng);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    var oPOI = &lt;span class="kwrd"&gt;new&lt;/span&gt; MyLocation() { Loc = &lt;span class="kwrd"&gt;new&lt;/span&gt; Location(lat, lng) };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    m_oList.Add(oPOI);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                    RenderPoint(oPOI);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; { }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            MessageBox.Show(sResult);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3375194943770563371?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3375194943770563371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3375194943770563371&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3375194943770563371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3375194943770563371'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/06/virtual-earth-silverlight-control-part.html' title='Virtual Earth Silverlight Control Part 2:  Locate Me'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_x0fXcQg3teU/Si1W_ILyKOI/AAAAAAAAACY/ST25ux7hEWg/s72-c/LocateMeInAkron.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2166576642465408646</id><published>2009-06-01T08:50:00.025-04:00</published><updated>2009-06-24T09:16:34.004-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bing Maps'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='serialization'/><category scheme='http://www.blogger.com/atom/ns#' term='Virtual Earth'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Using the Virtual Earth Silverlight Control - Part One</title><content type='html'>Debra and I took a trip around the country last month, 7500 miles of driving over 25 days. You can read about it at &lt;a href="http://www.wiredwalkabout.com/"&gt;http://www.wiredwalkabout.com/&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;One of the goals of the trip was to fieldtest technology, including the Virtual Earth Silverlight control. You can see the MIX09 presentation here at &lt;a href="http://videos.visitmix.com/MIX09/T34F"&gt;http://videos.visitmix.com/MIX09/T34F.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So you might be thinking, why not just do this from home? I believe that you can see the issues more clearly if you put yourself into the situations in which you expect the software to be used. After all, Pixar animators traveled to South America as inspiration for the movie "UP", and traveled along Route 66 in preparation for the movie "Cars".&lt;br /&gt;&lt;br /&gt;Along the way we were using a Garmin to plan our trip. This is an extremely valuable tool, but it was missing some features that would have been nice to have, so I decided to investigate the Virtual Earth Silverlight control to see what it would take to reproduce/extend the features in the Garmin. I have also done Telco applications in the past and I wanted to investigate how the mapping requirement in these applications could be accomplished in Silverlight.&lt;br /&gt;&lt;br /&gt;&lt;object width="618" height="478" class="BLOG_video_class" id="BLOG_video-d97e5d928affc608" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v23.nonxt8.googlevideo.com/videoplayback?id%3Dd97e5d928affc608%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D687BD244716A3663393CA1EA61F588034B49B8E5.3D691EE9B6B1948677D96DC7E3A8EAD57487F44D%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dd97e5d928affc608%26offsetms%3D5000%26itag%3Dw160%26sigh%3D_0-yEBniE7Z_YjlWjEO_IikAdQ8&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="618" height="478" bgcolor="#FFFFFF"flashvars="flvurl=http://v23.nonxt8.googlevideo.com/videoplayback?id%3Dd97e5d928affc608%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D687BD244716A3663393CA1EA61F588034B49B8E5.3D691EE9B6B1948677D96DC7E3A8EAD57487F44D%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dd97e5d928affc608%26offsetms%3D5000%26itag%3Dw160%26sigh%3D_0-yEBniE7Z_YjlWjEO_IikAdQ8&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Since this investigation was going to be more like building an application and less like an experiment, I am starting by writing code to persist my POCO domain model (Plain Old CLR Objects). I am using the OpenFileSave feature in Silverlight 3 to save my domain model as XML. The rest of this blog entry explains my model for persistence.&lt;br /&gt;&lt;br /&gt;For this application I am implementing my own XML serializer. The result (so far) is as follows. As the implementation grows I expect this file format to change. XML gives me some flexibility in reusing data from older files.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&amp;lt;?xml version=&lt;span class="str"&gt;"1.0"&lt;/span&gt; encoding=&lt;span class="str"&gt;"utf-8"&lt;/span&gt;?&amp;gt;&lt;br /&gt;&amp;lt;ModelSerializer&amp;gt;&lt;br /&gt;  &amp;lt;PointsOfInterest&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"39.730288305639185"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-83.310517678613749"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"34.004710072445405"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-89.814423928613749"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"32.572126585547366"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-96.669892678613763"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"30.436679980300028"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-98.032197366113763"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"31.304215774927229"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-103.74508799111376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"33.272989725895094"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-111.96286142861376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"36.445446009018042"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-118.24704111611376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"38.845986120977358"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-120.35641611611376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"37.463816739355629"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-122.11422861611376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"41.82646221909387"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-121.71872080361376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"45.511996049055"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-122.24606455361376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"47.478111391249712"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-122.20211924111376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"46.3676556511152"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-117.06051767861376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"45.604305565410648"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-110.68844736611376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"44.07759180028043"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-103.52536142861376"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"43.410903675485677"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-96.582002053613763"&lt;/span&gt; /&amp;gt;&lt;br /&gt;    &amp;lt;PointOfInterest Latitude=&lt;span class="str"&gt;"41.924626769221476"&lt;/span&gt; Longitude=&lt;span class="str"&gt;"-89.902314553613749"&lt;/span&gt; /&amp;gt;&lt;br /&gt;  &amp;lt;/PointsOfInterest&amp;gt;&lt;br /&gt;&amp;lt;/ModelSerializer&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The PointsOfInterest and PointOfInterest classes both implement the PersistTo XML and RecoverFrom XML methods defined in the IMapModel interface. Here is the code:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IMapModel&lt;br /&gt;    {&lt;br /&gt;        XElement PersistTo(ModelSerializer oSerializer, XElement oSelf);&lt;br /&gt;        IMapModel RecoverFrom(ModelSerializer oSerializer, XElement oElement);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PointsOfInterest : List&amp;lt;PointOfInterest&amp;gt;, IMapModel&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Serializer Methods&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; XElement PersistTo(ModelSerializer oSerializer, XElement oSelf)&lt;br /&gt;        {&lt;br /&gt;            XElement oXElement = &lt;span class="kwrd"&gt;new&lt;/span&gt; XElement(GetType().Name);&lt;br /&gt;            oSelf.Add(oXElement);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (IMapModel oIMap &lt;span class="kwrd"&gt;in&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;)&lt;br /&gt;                oIMap.PersistTo(oSerializer, oXElement);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oSelf;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IMapModel RecoverFrom(ModelSerializer oSerializer, XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sType = GetType().Name;&lt;br /&gt;            XElement oRefElement = oElement.Element(sType);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oElement.HasElements)&lt;br /&gt;                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (XElement oSubElement &lt;span class="kwrd"&gt;in&lt;/span&gt; oRefElement.Elements())&lt;br /&gt;                {&lt;br /&gt;                    IMapModel oChild = oSerializer.Import(&lt;span class="kwrd"&gt;this&lt;/span&gt;, oSubElement);&lt;br /&gt;&lt;br /&gt;                    PointOfInterest oPOI = oChild &lt;span class="kwrd"&gt;as&lt;/span&gt; PointOfInterest;&lt;br /&gt;                    &lt;span class="kwrd"&gt;if&lt;/span&gt; (oPOI != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Add(oPOI);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; PointOfInterest : IMapModel&lt;br /&gt;    {&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Location Loc { get; set; }&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Serializer Methods&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; XElement PersistTo(ModelSerializer oSerializer, XElement oSelf)&lt;br /&gt;        {&lt;br /&gt;            XElement oXElement = &lt;span class="kwrd"&gt;new&lt;/span&gt; XElement(GetType().Name);&lt;br /&gt;            oSelf.Add(oXElement);&lt;br /&gt;&lt;br /&gt;            oXElement.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; XAttribute(&lt;span class="str"&gt;"Latitude"&lt;/span&gt;,Loc.Latitude));&lt;br /&gt;            oXElement.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; XAttribute(&lt;span class="str"&gt;"Longitude"&lt;/span&gt;, Loc.Longitude));&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oXElement;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IMapModel RecoverFrom(ModelSerializer oSerializer, XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            Loc = &lt;span class="kwrd"&gt;new&lt;/span&gt; Location(&lt;span class="kwrd"&gt;double&lt;/span&gt;.Parse(oElement.Attribute(&lt;span class="str"&gt;"Latitude"&lt;/span&gt;).Value), &lt;span class="kwrd"&gt;double&lt;/span&gt;.Parse(oElement.Attribute(&lt;span class="str"&gt;"Longitude"&lt;/span&gt;).Value));&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;this&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is not the first time I have implemented my own serializer. Most of my applications implement a highly interrelated domain model, combining objects sourced from many data sources into a domain model with many pointers and references. I have found the additional control I get over the serialization implementation to outweigh the effort of implementation. However, before this series of posts is finished, I plan on investigating the Silverlight 3 tools for persistence in XAML, XML and JSON.&lt;br /&gt;Here is the code for ModelSerializer and the save and restore methods that start the process.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ModelSerializer&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        &lt;span class="preproc"&gt;#region&lt;/span&gt; Compute Type&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Type ComputeType(XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sType = oElement.Name.ToString();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; ComputeType(sType);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Type ComputeType(&lt;span class="kwrd"&gt;object&lt;/span&gt; oObject)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oObject.GetType().IsSubclassOf(&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Type)))&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; ComputeType(oObject &lt;span class="kwrd"&gt;as&lt;/span&gt; Type);&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; ComputeType(oObject.ToString());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; Dictionary&amp;lt;String, Type&amp;gt; m_oTDictionary = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Dictionary&amp;lt;String, Type&amp;gt; TypeHash&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (m_oTDictionary == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                {&lt;br /&gt;                    m_oTDictionary = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;String, Type&amp;gt;();&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"double"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Double));&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"string"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(String));&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"boolean"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Boolean));&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"bool"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Boolean));&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"integer"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Int32));&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"int32"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(Int32));&lt;br /&gt;                    m_oTDictionary.Add(&lt;span class="str"&gt;"object"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;object&lt;/span&gt;));&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; m_oTDictionary;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_oTDictionary = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&lt;br /&gt;     &lt;br /&gt;     &lt;br /&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; XDocument m_oDocument = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; XDocument Document&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (m_oDocument == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                    m_oDocument = &lt;span class="kwrd"&gt;new&lt;/span&gt; XDocument();&lt;br /&gt;&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; m_oDocument;&lt;br /&gt;            }&lt;br /&gt;            set&lt;br /&gt;            {&lt;br /&gt;                m_oDocument = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Write(StreamWriter oStream)&lt;br /&gt;        {&lt;br /&gt;            Document.Save(oStream);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; XDocument Read(StreamReader oStream)&lt;br /&gt;        {&lt;br /&gt;            Document = XDocument.Parse(oStream.ReadToEnd());&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; Document;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IMapModel CreateObject(XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            Type oType = ComputeType(oElement);&lt;br /&gt;            &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; Activator.CreateInstance(oType) &lt;span class="kwrd"&gt;as&lt;/span&gt; IMapModel;&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                oType = ComputeType(oElement);&lt;br /&gt;                &lt;span class="kwrd"&gt;string&lt;/span&gt; sType = oElement.Name.ToString();&lt;br /&gt;                &lt;span class="kwrd"&gt;string&lt;/span&gt; sMessage = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Type {0} not created. {1}"&lt;/span&gt;, sType, ex.Message);&lt;br /&gt;                MessageBox.Show(sMessage);&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; XElement Export(IMapModel oObject, XElement oParent)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; SerializeObject(oObject, oParent);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; IMapModel Import(IMapModel oObject, XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            IMapModel oResult = CreateObject(oElement);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oResult != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                DeSerializeObject(oResult, oElement);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oResult;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Serialize(IMapModel oObject)&lt;br /&gt;        {&lt;br /&gt;            Serialize(oObject, Document);&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Serialize(IMapModel oObject, XDocument oDocument)&lt;br /&gt;        {&lt;br /&gt;            XElement oElement = &lt;span class="kwrd"&gt;new&lt;/span&gt; XElement(GetType().Name);&lt;br /&gt;            oDocument.Add(oElement);&lt;br /&gt;            SerializeObject(oObject, oElement);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IMapModel DeSerialize(IMapModel oObject)&lt;br /&gt;        {&lt;br /&gt;            IMapModel oResult = DeSerialize(Document, oObject);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oResult;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IMapModel DeSerialize(XDocument oDocument, IMapModel oTarget)&lt;br /&gt;        {&lt;br /&gt;            XElement oRoot = oDocument.Root;&lt;br /&gt;            IMapModel oResult = DeSerializeObject(oTarget, oRoot);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oResult;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; XElement SerializeObject(IMapModel oObject, XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oObject.PersistTo(&lt;span class="kwrd"&gt;this&lt;/span&gt;, oElement);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; IMapModel DeSerializeObject(IMapModel oObject, XElement oElement)&lt;br /&gt;        {&lt;br /&gt;            oObject.RecoverFrom(&lt;span class="kwrd"&gt;this&lt;/span&gt;, oElement);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oObject;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; btnSave_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            Button oButton = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; Button;&lt;br /&gt;&lt;br /&gt;            SaveFileDialog sfd = &lt;span class="kwrd"&gt;new&lt;/span&gt; SaveFileDialog()&lt;br /&gt;            {&lt;br /&gt;                DefaultExt = &lt;span class="str"&gt;"xml"&lt;/span&gt;,&lt;br /&gt;                Filter = &lt;span class="str"&gt;"XML files (*.xml)*.xmlAll files (*.*)*.*"&lt;/span&gt;,&lt;br /&gt;                FilterIndex = 1&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;bool&lt;/span&gt;? result = sfd.ShowDialog();&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (result == &lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamWriter oStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(sfd.OpenFile()))&lt;br /&gt;                    {&lt;br /&gt;                        ModelSerializer oSerializer = &lt;span class="kwrd"&gt;new&lt;/span&gt; ModelSerializer();&lt;br /&gt;                        oSerializer.Serialize(m_oList);&lt;br /&gt;                        oSerializer.Write(oStream);&lt;br /&gt;                        oStream.Close();&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;br /&gt;                {&lt;br /&gt;                    MessageBox.Show(ex.Message);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; btnLoad_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            Button oButton = sender &lt;span class="kwrd"&gt;as&lt;/span&gt; Button;&lt;br /&gt;&lt;br /&gt;            OpenFileDialog ofd = &lt;span class="kwrd"&gt;new&lt;/span&gt; OpenFileDialog()&lt;br /&gt;            {&lt;br /&gt;                Filter = &lt;span class="str"&gt;"XML files (*.xml)*.xmlAll files (*.*)*.*"&lt;/span&gt;,&lt;br /&gt;                FilterIndex = 1&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;bool&lt;/span&gt;? result = ofd.ShowDialog();&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (result == &lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;br /&gt;                {&lt;br /&gt;                    &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamReader oStream = ofd.File.OpenText())&lt;br /&gt;                    {&lt;br /&gt;                        ModelSerializer oSerializer = &lt;span class="kwrd"&gt;new&lt;/span&gt; ModelSerializer();&lt;br /&gt;                        oSerializer.Read(oStream);&lt;br /&gt;                        oSerializer.DeSerialize(m_oList);&lt;br /&gt;                        oStream.Close();&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (PointOfInterest oPOI &lt;span class="kwrd"&gt;in&lt;/span&gt; m_oList)&lt;br /&gt;                        RenderPoint(oPOI);&lt;br /&gt;&lt;br /&gt;                }&lt;br /&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception ex)&lt;br /&gt;                {&lt;br /&gt;                    MessageBox.Show(ex.Message);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All the source code is on Codeplex:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://vearthmappingexample.codeplex.com/"&gt;http://vearthmappingexample.codeplex.com/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2166576642465408646?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2166576642465408646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2166576642465408646&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2166576642465408646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2166576642465408646'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/06/using-virtual-earth-silverlight-control.html' title='Using the Virtual Earth Silverlight Control - Part One'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3242008612809882566</id><published>2009-05-14T11:42:00.018-04:00</published><updated>2009-06-09T11:20:03.372-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='directory name is invalid'/><title type='text'>Error Message: The directory name is invalid</title><content type='html'>Over the last week I was working on serialization of a generic domain model to XML. I had seen a few examples of using Silverlight 3's new feature SaveFileDialog(), so I implemented it in order to save the XML to my local hard drive. I got this error - the directory name is invalid.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_s1N_RQkyQXU/Sg2OfvhGwmI/AAAAAAAAAGA/Vf2YPylTPvI/s1600-h/ErrorMsgBetter.jpg"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 179px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5336077809486316130" border="0" alt="" src="http://4.bp.blogspot.com/_s1N_RQkyQXU/Sg2OfvhGwmI/AAAAAAAAAGA/Vf2YPylTPvI/s400/ErrorMsgBetter.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I asked a friend who is learning Silverlight to create a small project using SaveFileDialog() command, and it worked for him without a problem. He sent me the project, I ran it unchanged, and I go the same error. So I ran this Google search:&lt;br /&gt;&lt;br /&gt;Silverlight "The directory name is invalid"&lt;br /&gt;&lt;br /&gt;and found some helpful entries about Protected Mode in IE. I followed the instructions to turn off Protected Mode:&lt;br /&gt;&lt;br /&gt;Tool .. Internet Options .. Security. Here is the picture.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_s1N_RQkyQXU/Sg2RFlO2XuI/AAAAAAAAAGI/QSYZigeTZHY/s1600-h/ProtectionModeBetter.jpg"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 313px; DISPLAY: block; HEIGHT: 400px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5336080658583674594" border="0" alt="" src="http://4.bp.blogspot.com/_s1N_RQkyQXU/Sg2RFlO2XuI/AAAAAAAAAGI/QSYZigeTZHY/s400/ProtectionModeBetter.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I checked MSN to see what I was giving up by unchecking the box. This is what it said:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Understanding Protected Mode&lt;br /&gt;&lt;br /&gt;Protected Mode is an important step forward in security for Internet Explorer (IE); it helps protect users from attack by running an IE process with greatly restricted privileges on Windows Vista. While Protected Mode does not protect against all forms of attack, it significantly reduces the ability of an attack to write, alter, or destroy data on the user's machine or to install malicious code.&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;Disabling this would sound bad to any user. Furthermore, being in the reduced security mode affected my Google home page and my Twitter login.&lt;br /&gt;&lt;br /&gt;What looked like this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_x0fXcQg3teU/SgzZEGxqRyI/AAAAAAAAACQ/TjRDhd7nqbk/s1600-h/TurnedOn.png"&gt;&lt;img style="WIDTH: 456px; HEIGHT: 208px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5335878323088803618" border="0" alt="" src="http://1.bp.blogspot.com/_x0fXcQg3teU/SgzZEGxqRyI/AAAAAAAAACQ/TjRDhd7nqbk/s320/TurnedOn.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_x0fXcQg3teU/SgzY2hLrpoI/AAAAAAAAACI/tbOyU59_4SU/s1600-h/TurnedOff.png"&gt;&lt;img style="WIDTH: 460px; HEIGHT: 191px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5335878089659098754" border="0" alt="" src="http://4.bp.blogspot.com/_x0fXcQg3teU/SgzY2hLrpoI/AAAAAAAAACI/tbOyU59_4SU/s320/TurnedOff.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, this would be very confusing for someone using your application, who is expecting the File...Save option to act like it would in any other desktop application. In fact, turning off Protected Mode is likely to scare users away. For this reason I have decided to add other options for the user to persist information, like saving to an account on the server or in isolated storage.&lt;br /&gt;&lt;br /&gt;To finish on a positive note the blogs say that Microsoft will be fixing this issue before the final release of Silverlight 3.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3242008612809882566?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3242008612809882566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3242008612809882566&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3242008612809882566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3242008612809882566'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/05/error-message-directory-name-is-invalid.html' title='Error Message: The directory name is invalid'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_s1N_RQkyQXU/Sg2OfvhGwmI/AAAAAAAAAGA/Vf2YPylTPvI/s72-c/ErrorMsgBetter.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-6300380491382512060</id><published>2009-05-08T22:33:00.015-04:00</published><updated>2009-06-09T11:20:03.372-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Beat Box Application - Part 3: Playing Media Elements</title><content type='html'>In this part, I will talk about a tip I learned while working with media sources, and some insight I have gained when playing multiple media sources simultaneously. The source code for the complete project is on Codeplex. The complete source code for the beat box can be downloaded here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://drumpanel.codeplex.com/"&gt;http://drumpanel.codeplex.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Before this project, whenever I worked with MediaElements and media sources, I always loaded the sources dynamically from the ClientBin folder off of the server. This makes sense if the user is selecting from a number of sources or if the sources are large. However, in this application -- since the drum sound files are small and they are all likely to play at some time during the song -- I decided to load them as resources into the actual XAP file that is downloaded when the application is started. To do this you need to specify the file as a resource.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_x0fXcQg3teU/SgTv9fzH6JI/AAAAAAAAABw/cvWJWWghuAM/s1600-h/SetasResource.png"&gt;&lt;img style="WIDTH: 196px; HEIGHT: 320px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5333651698500495506" border="0" alt="" src="http://3.bp.blogspot.com/_x0fXcQg3teU/SgTv9fzH6JI/AAAAAAAAABw/cvWJWWghuAM/s320/SetasResource.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then you need to load the source file into the MediaElement using the following code:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;           &lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0;&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; sSounds = &lt;span class="str"&gt;"crash;hhclosed;hhopen;kick;snare;tom1;tom2;tom3"&lt;/span&gt;;&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (&lt;span class="kwrd"&gt;string&lt;/span&gt; sKey &lt;span class="kwrd"&gt;in&lt;/span&gt; sSounds.Split(&lt;span class="str"&gt;';'&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                &lt;span class="kwrd"&gt;string&lt;/span&gt; sResource = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;@"DrumPanel;component/sounds/{0}.mp3"&lt;/span&gt;, sKey);&lt;br /&gt;                StreamResourceInfo oStream = Application.GetResourceStream(&lt;span class="kwrd"&gt;new&lt;/span&gt; Uri(sResource, System.UriKind.Relative));&lt;br /&gt;                Sounds.Add(i,oStream);&lt;br /&gt;&lt;br /&gt;                MediaElement oElement = &lt;span class="kwrd"&gt;new&lt;/span&gt; MediaElement();&lt;br /&gt;                Elements.Add(i, oElement);&lt;br /&gt;                LayoutRoot.Children.Add(oElement);&lt;br /&gt;                i++;&lt;br /&gt;            }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As for playing the sounds, the MediaElement is reading from a stream and the sound will start playing from the beginning. I have set AutoPlay = False so it will not play until I call the method Play. Also, I have learned through trial and error that in order to replay the sound, you first need to call the Stop method before you call the Play method again.&lt;br /&gt;&lt;br /&gt;A drum machine plays a rhythm, which means on any beat, any one of the sounds can be played. Every sound has the same duration. If we were creating a piano synthesizer we would need to account for the duration of each note, like quarter notes and whole notes, but for drums this is not an issue.&lt;br /&gt;&lt;br /&gt;Here is the code that plays all the sounds on each kit panel when the timer triggers a new beat. Each drum sound is stopped and then the active ones are played again on the next beat. The interesting thing about making music using software is you can do things you could never do in real life, like play all the drum sounds at once.&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; Timer_Tick(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            PlayBeat();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PlayBeat()&lt;br /&gt;        {&lt;br /&gt;            MovingCursor++;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (MovingCursor &amp;gt;= MaxCount)&lt;br /&gt;                MovingCursor = 0;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BackBeat()&lt;br /&gt;        {&lt;br /&gt;            MovingCursor--;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (MovingCursor &amp;lt;= 0)&lt;br /&gt;                MovingCursor = MaxCount-1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MovingCursor&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt;)GetValue(MovingCursorProperty); }&lt;br /&gt;            set { SetValue(MovingCursorProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DependencyProperty MovingCursorProperty =&lt;br /&gt;            DependencyProperty.Register(&lt;span class="str"&gt;"MovingCursor"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(BeatPanel),&lt;br /&gt;            &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyMetadata(0,OnCursorChange));&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnCursorChange(DependencyObject obj, DependencyPropertyChangedEventArgs args)&lt;br /&gt;        {&lt;br /&gt;            BeatPanel oPanel = obj &lt;span class="kwrd"&gt;as&lt;/span&gt; BeatPanel;&lt;br /&gt;            oPanel.KitRest((&lt;span class="kwrd"&gt;int&lt;/span&gt;)args.OldValue);&lt;br /&gt;            oPanel.KitPlay((&lt;span class="kwrd"&gt;int&lt;/span&gt;)args.NewValue);&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Play()&lt;br /&gt;        {&lt;br /&gt;            Background = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Black);&lt;br /&gt;            &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 8; i++)&lt;br /&gt;            {&lt;br /&gt;                Ellipse oEllipse = Children[i] &lt;span class="kwrd"&gt;as&lt;/span&gt; Ellipse;&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (oEllipse.Opacity &amp;lt; .6)&lt;br /&gt;                    &lt;span class="kwrd"&gt;continue&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;                StreamResourceInfo oInfo = Sounds[i];&lt;br /&gt;                MediaElement oElement = Elements[i];&lt;br /&gt;                oElement.SetSource(oInfo.Stream);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-6300380491382512060?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/6300380491382512060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=6300380491382512060&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/6300380491382512060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/6300380491382512060'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/05/beat-box-application-part-3-playing.html' title='Beat Box Application - Part 3: Playing Media Elements'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_x0fXcQg3teU/SgTv9fzH6JI/AAAAAAAAABw/cvWJWWghuAM/s72-c/SetasResource.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-3156342071879273787</id><published>2009-05-01T22:49:00.019-04:00</published><updated>2009-06-09T11:20:03.372-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='custom panel'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='hit testing'/><title type='text'>Beat Box Application - Part 2: Custom Panel Hit Testing</title><content type='html'>The beat box application is constructed using a nested set of custom panels. The Kit Panel is a vertical arrangement of ellipses, one for each drum sound. Kit Panels are arranged horizontally on a Beat Panel and played from left to right. The drum rhythm is controlled by a timer that generates 120 / beats per min. The complete source code for the beat box can be downloaded here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://drumpanel.codeplex.com/"&gt;http://drumpanel.codeplex.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Although it only took about 4 hours to build this application, during its development I discovered some code refactoring that I now use as best practice when creating custom panels. I thought I would discuss them here on the blog, because once implemented in the source code, the issues become obscured.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Custom panel layout and hit test behaviors&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Did you know that the width and height of a custom panel are not calculated by default just because you load the XAML elements? Furthermore, you will not really notice this because the XAML elements will layout correctly even if the width and height are set to zero or NAN. However, having the correct width and height are critical to painting the background color and to detecting a mouse hit on the panel itself.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Watching this video could save you hours of fustration:&lt;br /&gt;&lt;br /&gt;&lt;object width="608" height="494" class="BLOG_video_class" id="BLOG_video-de0fb7d7613b1eff" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v23.nonxt7.googlevideo.com/videoplayback?id%3Dde0fb7d7613b1eff%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D483EC3C8CD9AE65557A773F695FA3E3361B9125B.72B2D4117B34FCEA5C08E6CB0F4DD50DF3A1A0C1%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dde0fb7d7613b1eff%26offsetms%3D5000%26itag%3Dw160%26sigh%3D6Wnqor7OOFa5FIYePjxWFCZfcbo&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="608" height="494" bgcolor="#FFFFFF"flashvars="flvurl=http://v23.nonxt7.googlevideo.com/videoplayback?id%3Dde0fb7d7613b1eff%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D483EC3C8CD9AE65557A773F695FA3E3361B9125B.72B2D4117B34FCEA5C08E6CB0F4DD50DF3A1A0C1%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dde0fb7d7613b1eff%26offsetms%3D5000%26itag%3Dw160%26sigh%3D6Wnqor7OOFa5FIYePjxWFCZfcbo&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Taking advantage of WPF dependency properties&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;WPF is a model that forces you to think about graphic interaction differently than using HTML, WinForms, or ASP.NET. The introduction of binding and use of the dependency property pattern let me refactor the code into a very simplified form. &lt;pre class="csharpcode"&gt; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MovingCursor&lt;br /&gt;{&lt;br /&gt;     get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt;)GetValue(MovingCursorProperty); }&lt;br /&gt;     set { SetValue(MovingCursorProperty, &lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="rem"&gt;// Using a DependencyProperty as the backing store for Cursor. This enables animation, styling, binding, etc...&lt;/span&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DependencyProperty MovingCursorProperty =&lt;br /&gt;DependencyProperty.Register(&lt;span class="str"&gt;"MovingCursor"&lt;/span&gt;, &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt;), &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(BeatPanel),&lt;br /&gt;&lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyMetadata(0,OnCursorChange));&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnCursorChange(DependencyObject obj, DependencyPropertyChangedEventArgs args)&lt;br /&gt;{&lt;br /&gt;     BeatPanel oPanel = obj &lt;span class="kwrd"&gt;as&lt;/span&gt; BeatPanel;&lt;br /&gt;     oPanel.KitRest((&lt;span class="kwrd"&gt;int&lt;/span&gt;)args.OldValue);&lt;br /&gt;     oPanel.KitPlay((&lt;span class="kwrd"&gt;int&lt;/span&gt;)args.NewValue);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;What I really love about dependency properties in this example is that they automatically track changes in the value. When a value changes, you can work with both the old value and the new value. This is great in an application in which I am moving the cursor, because in this case I not only need to change the color of the background on the currently selected item, but I also need to clear the background color of the previously selected item, and start and stop the sounds. This in turn lets me simplify the API for playing the beat:&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; PlayBeat()&lt;br /&gt;        {&lt;br /&gt;            MovingCursor++;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (MovingCursor &amp;gt;= MaxCount)&lt;br /&gt;                MovingCursor = 0;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BackBeat()&lt;br /&gt;        {&lt;br /&gt;            MovingCursor--;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (MovingCursor &amp;lt;= 0)&lt;br /&gt;                MovingCursor = MaxCount-1;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;And it can easily be driven from the key board or mouse just by setting the value of the MovingCursor. Here are some examples:&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; BeatPanel_MouseLeftButtonDown(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, MouseButtonEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            Point oPoint = e.GetPosition(&lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;br /&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (UIElement oElement &lt;span class="kwrd"&gt;in&lt;/span&gt; VisualTreeHelper.FindElementsInHostCoordinates(oPoint, &lt;span class="kwrd"&gt;this&lt;/span&gt;))&lt;br /&gt;            {&lt;br /&gt;                KitPanel oKit = oElement &lt;span class="kwrd"&gt;as&lt;/span&gt; KitPanel;&lt;br /&gt;                &lt;span class="kwrd"&gt;if&lt;/span&gt; (oKit != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                    MovingCursor = (&lt;span class="kwrd"&gt;int&lt;/span&gt;)oKit.Tag;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-3156342071879273787?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=de0fb7d7613b1eff&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/3156342071879273787/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=3156342071879273787&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3156342071879273787'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/3156342071879273787'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/05/beat-box-application-part-2-custom.html' title='Beat Box Application - Part 2: Custom Panel Hit Testing'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-359795321297777098</id><published>2009-04-28T23:16:00.002-04:00</published><updated>2009-06-09T11:20:03.373-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight 3'/><category scheme='http://www.blogger.com/atom/ns#' term='2D drawing'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='element binding'/><category scheme='http://www.blogger.com/atom/ns#' term='visio'/><title type='text'>Element Binding That Acts Like Visio Glue</title><content type='html'>In previous posts I discussed drag and drop techniques, inspired by my years of work with Visio. Now that Silverlight 3 has element to element binding, I was inspired to investigate ways to implement Visio glue behaviors in Silverlight.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;object width="800" height="600" class="BLOG_video_class" id="BLOG_video-a877b583394201cd" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v19.nonxt7.googlevideo.com/videoplayback?id%3Da877b583394201cd%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3DA2CF798E75EEA88A090EC4E4D5AC0165E403172.3B206217FBDB7D3D1EFC395FFDB9B7223566A606%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Da877b583394201cd%26offsetms%3D5000%26itag%3Dw160%26sigh%3DdKCsi8bk0uWfuQqxRV7mo73xYrI&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="800" height="600" bgcolor="#FFFFFF"flashvars="flvurl=http://v19.nonxt7.googlevideo.com/videoplayback?id%3Da877b583394201cd%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3DA2CF798E75EEA88A090EC4E4D5AC0165E403172.3B206217FBDB7D3D1EFC395FFDB9B7223566A606%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Da877b583394201cd%26offsetms%3D5000%26itag%3Dw160%26sigh%3DdKCsi8bk0uWfuQqxRV7mo73xYrI&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;The following is the XAML shown in the video:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&amp;lt;UserControl x:Class=&lt;span class="str"&gt;"Sketch.MainPage"&lt;/span&gt;&lt;br /&gt;    xmlns=&lt;span class="str"&gt;"http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;/span&gt;&lt;br /&gt;    xmlns:x=&lt;span class="str"&gt;"http://schemas.microsoft.com/winfx/2006/xaml"&lt;/span&gt;&lt;br /&gt;    xmlns:v=&lt;span class="str"&gt;"clr-namespace:ApprenticeView;assembly=ApprenticeView"&lt;/span&gt;&lt;br /&gt;    Width=&lt;span class="str"&gt;"400"&lt;/span&gt; Height=&lt;span class="str"&gt;"300"&lt;/span&gt;&amp;gt;&lt;br /&gt;    &amp;lt;Grid x:Name=&lt;span class="str"&gt;"LayoutRoot"&lt;/span&gt; Background=&lt;span class="str"&gt;"gray"&lt;/span&gt;&amp;gt;&lt;br /&gt;        &amp;lt;v:SketchPage x:Name=&lt;span class="str"&gt;"MyPage"&lt;/span&gt;&amp;gt;&lt;br /&gt;            &amp;lt;v:OneDLink&lt;br /&gt;                X1=&lt;span class="str"&gt;"{Binding PinX, ElementName=RedSquare}"&lt;/span&gt;&lt;br /&gt;                Y1=&lt;span class="str"&gt;"{Binding PinY, ElementName=RedSquare}"&lt;/span&gt;&lt;br /&gt;                X2=&lt;span class="str"&gt;"{Binding PinX, ElementName=BlueSquare}"&lt;/span&gt;&lt;br /&gt;                Y2=&lt;span class="str"&gt;"{Binding PinY, ElementName=BlueSquare}"&lt;/span&gt;&lt;br /&gt;                &amp;gt;               &lt;br /&gt;            &amp;lt;/v:OneDLink&amp;gt;&lt;br /&gt;            &amp;lt;v:SketchShape x:Name=&lt;span class="str"&gt;"RedSquare"&lt;/span&gt;&lt;br /&gt;                           v:SketchPanel.PinX=&lt;span class="str"&gt;"100"&lt;/span&gt;&lt;br /&gt;                           v:SketchPanel.PinY=&lt;span class="str"&gt;"100"&lt;/span&gt;&lt;br /&gt;                           Background=&lt;span class="str"&gt;"Red"&lt;/span&gt;&lt;br /&gt;                           Width=&lt;span class="str"&gt;"40"&lt;/span&gt;&lt;br /&gt;                           Height=&lt;span class="str"&gt;"30"&lt;/span&gt; &amp;gt;&lt;br /&gt;           &lt;br /&gt;            &amp;lt;/v:SketchShape&amp;gt;&lt;br /&gt;            &amp;lt;v:SketchShape x:Name=&lt;span class="str"&gt;"BlueSquare"&lt;/span&gt;&lt;br /&gt;                           v:SketchPanel.PinX=&lt;span class="str"&gt;"300"&lt;/span&gt;&lt;br /&gt;                           v:SketchPanel.PinY=&lt;span class="str"&gt;"140"&lt;/span&gt;&lt;br /&gt;                           Background=&lt;span class="str"&gt;"Blue"&lt;/span&gt;&lt;br /&gt;                           Width=&lt;span class="str"&gt;"40"&lt;/span&gt;&lt;br /&gt;                           Height=&lt;span class="str"&gt;"30"&lt;/span&gt; &amp;gt;&lt;br /&gt;           &lt;br /&gt;            &amp;lt;/v:SketchShape&amp;gt;&lt;br /&gt;        &amp;lt;/v:SketchPage&amp;gt;&lt;br /&gt;    &amp;lt;/Grid&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Dependency properties do all the heavy lifting in this example. This is because they send and receive notifications when their values change. To take advantage of this you need to program your custom XAML controls in a very declarative way, reacting to the events that occur naturally as Silverlight renders the screen.&lt;/p&gt;&lt;br /&gt;PinX and PinY are attached properties of a SketchPage, and are used to position SketchShapes on the page (see the entry: Replicating a Visio Page Using a Silverlight Panel).&lt;br /&gt;&lt;br /&gt;The OneDLink shape has four dependency properties -- X1,Y1,X2,Y2 -- that represent the start and finish of a line. These properties are bound to the PinX and PinY of the shape using the element binding syntax:&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;&amp;lt;v:OneDLink&lt;br /&gt;     X1=&lt;span class="str"&gt;"{Binding PinX, ElementName=RedSquare}"&lt;/span&gt;&lt;br /&gt;     Y1=&lt;span class="str"&gt;"{Binding PinY, ElementName=RedSquare}"&lt;/span&gt;&lt;br /&gt;     X2=&lt;span class="str"&gt;"{Binding PinX, ElementName=BlueSquare}"&lt;/span&gt;&lt;br /&gt;     Y2=&lt;span class="str"&gt;"{Binding PinY, ElementName=BlueSquare}"&lt;/span&gt;&lt;br /&gt;     &amp;gt;                &lt;br /&gt;&amp;lt;/v:OneDLink&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The last bit of magic is in the code of the OneDLink class, because X1,Y1,X2,Y2 call InvalidateRouting(); when their value changes.&lt;/p&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;double&lt;/span&gt; Y2&lt;br /&gt;        {&lt;br /&gt;            get { &lt;span class="kwrd"&gt;return&lt;/span&gt; (&lt;span class="kwrd"&gt;double&lt;/span&gt;)GetValue(Y2Property); }&lt;br /&gt;            set { SetValue(Y2Property, &lt;span class="kwrd"&gt;value&lt;/span&gt;); }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DependencyProperty Y2Property =&lt;br /&gt;            DependencyProperty.Register(&lt;span class="str"&gt;"Y2"&lt;/span&gt;,&lt;br /&gt;            &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(&lt;span class="kwrd"&gt;double&lt;/span&gt;),&lt;br /&gt;            &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(OneDLink),&lt;br /&gt;            &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyMetadata(0.0, &lt;span class="kwrd"&gt;new&lt;/span&gt; PropertyChangedCallback(OnRouteChanged)));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnRouteChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)&lt;br /&gt;        {&lt;br /&gt;            OneDLink oPanel = obj &lt;span class="kwrd"&gt;as&lt;/span&gt; OneDLink;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (oPanel != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;                oPanel.InvalidateRouting();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InvalidateRouting()&lt;br /&gt;        {&lt;br /&gt;            CreateRouting();&lt;br /&gt;            InvalidateArrange();&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;CreateRouting() does the math that generates a line between the two end points.&lt;/p&gt;&lt;br /&gt;&lt;pre class="csharpcode"&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;virtual&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CreateRouting()&lt;br /&gt;        {&lt;br /&gt;            Children.Clear();&lt;br /&gt;            AddChild(SmartRouting(X1, Y1, X2, Y2));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;protected&lt;/span&gt; Polyline SmartRouting(&lt;span class="kwrd"&gt;double&lt;/span&gt; dX1, &lt;span class="kwrd"&gt;double&lt;/span&gt; dY1, &lt;span class="kwrd"&gt;double&lt;/span&gt; dX2, &lt;span class="kwrd"&gt;double&lt;/span&gt; dY2)&lt;br /&gt;        {&lt;br /&gt;            Point oUpperLeft = &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(Math.Min(dX1, dX2), Math.Min(dY1, dY2));&lt;br /&gt;            Point oLowerRight = &lt;span class="kwrd"&gt;new&lt;/span&gt; Point(Math.Max(dX1, dX2), Math.Max(dY1, dY2));&lt;br /&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//Make sure these is at least 3.0 to render the line, just in case&lt;/span&gt;&lt;br /&gt;            &lt;span class="rem"&gt;//it is vertical or horizontal&lt;/span&gt;&lt;br /&gt;            Width = Math.Abs(oLowerRight.X - oUpperLeft.X) + 3.0;&lt;br /&gt;            Height = Math.Abs(oLowerRight.Y - oUpperLeft.Y) + 3.0;&lt;br /&gt;&lt;br /&gt;            PointCollection oColl = &lt;span class="kwrd"&gt;new&lt;/span&gt; PointCollection();&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (dX1 &amp;lt;= dX2 &amp;amp;&amp;amp; dY1 &amp;lt;= dY2)&lt;br /&gt;            {&lt;br /&gt;                oColl.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Point(0, 0));&lt;br /&gt;                oColl.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Point(Width, Height));&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt; &lt;span class="kwrd"&gt;if&lt;/span&gt; (dX1 &amp;gt; dX2 &amp;amp;&amp;amp; dY1 &amp;gt; dY2)&lt;br /&gt;            {&lt;br /&gt;                oColl.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Point(0, 0));&lt;br /&gt;                oColl.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Point(Width, Height));&lt;br /&gt;            }&lt;br /&gt;            &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;            {&lt;br /&gt;                oColl.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Point(0, Height));&lt;br /&gt;                oColl.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Point(Width, 0));&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            Polyline oPoly = &lt;span class="kwrd"&gt;new&lt;/span&gt; Polyline();&lt;br /&gt;            oPoly.SetValue(Polyline.PointsProperty, oColl);&lt;br /&gt;            oPoly.StrokeThickness = 2.0;&lt;br /&gt;            oPoly.Stroke = &lt;span class="kwrd"&gt;new&lt;/span&gt; SolidColorBrush(Colors.Blue);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; oPoly;&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I know that the code samples I posted are not complete enough to reproduce the example shown in the video simply by cutting and pasting the code into a Silverlight 3 project. I decided to remove the complex issues associated with building a full-featured 2D drawing system, and focus on what is needed to make element binding work automatically in custom user controls.&lt;/p&gt;In the future there will be more posts on creating a full-featured 2D drawing system in Silverlight.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-359795321297777098?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=a877b583394201cd&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/359795321297777098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=359795321297777098&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/359795321297777098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/359795321297777098'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/element-binding-that-acts-like-visio.html' title='Element Binding That Acts Like Visio Glue'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2232229645767964714</id><published>2009-04-28T08:18:00.000-04:00</published><updated>2009-06-09T11:20:03.373-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='custom panel'/><category scheme='http://www.blogger.com/atom/ns#' term='MediaElement'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Beat Box Application - Part 1  overview</title><content type='html'>I was searching the web for Silverlight applications the used the WPF MediaElement, and I came across these applications / demos:&lt;br /&gt;&lt;br /&gt;John Papa has a nice chord finder application:&lt;br /&gt;&lt;a href="http://johnpapa.net/silverlight/silverlight-chord-finder/"&gt;http://johnpapa.net/silverlight/silverlight-chord-finder/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Pete Brown has built a virtual synthesizer keyboard:&lt;br /&gt;&lt;a href="http://community.irritatedvowel.com/blogs/pete_browns_blog/archive/2009/03/23/Creating-Sound-using-MediaStreamSource-in-Silverlight-3-Beta.aspx"&gt;http://community.irritatedvowel.com/blogs/pete_browns_blog/archive/2009/03/23/Creating-Sound-using-MediaStreamSource-in-Silverlight-3-Beta.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;During the search I found eight mp3 files that play drum sounds "crash; hhclosed; hhopen; kick; snare; tom1; tom2; tom3". This and my recent knowledge of creating custom layout panels inspired me to create a beat box application. This is what I was able to build in about 3 hours.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="515" height="404" class="BLOG_video_class" id="BLOG_video-174986786c93cdb0" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v19.nonxt3.googlevideo.com/videoplayback?id%3D174986786c93cdb0%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D30FB3222B7D9DB798700CA4B0BDCDEDCCFA0F75C.7148CAB58326CEAC321602FE7DF4EBE72357851C%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D174986786c93cdb0%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dju59gnk5Zwedc57g6MGbUE9ACHc&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="515" height="404" bgcolor="#FFFFFF"flashvars="flvurl=http://v19.nonxt3.googlevideo.com/videoplayback?id%3D174986786c93cdb0%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D30FB3222B7D9DB798700CA4B0BDCDEDCCFA0F75C.7148CAB58326CEAC321602FE7DF4EBE72357851C%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D174986786c93cdb0%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dju59gnk5Zwedc57g6MGbUE9ACHc&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;I have always been interested in the relationship between math and music, so I constructed the API so the user could fill the beat box using lambda expressions. But before I go into that I need to explain the math used to control the box.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_x0fXcQg3teU/SfOonkJt7aI/AAAAAAAAABo/in_zBSuAr3o/s1600-h/BeatLayout.png"&gt;&lt;/a&gt;&lt;a href="http://2.bp.blogspot.com/_s1N_RQkyQXU/SfTYjuktVNI/AAAAAAAAABw/CHKo4LVCfhM/s1600-h/BeatLayout.png"&gt;&lt;img style="MARGIN: 0px 10px 10px 0px; WIDTH: 569px; FLOAT: left; HEIGHT: 308px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5329122367395157202" border="0" alt="" src="http://2.bp.blogspot.com/_s1N_RQkyQXU/SfTYjuktVNI/AAAAAAAAABw/CHKo4LVCfhM/s400/BeatLayout.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the picture, there are 2 custom panels, the BeatPanel is horizontal. It is composed on many KitPanel's. Each KitPanel is composed of 8 Ellipses, one for each sound.&lt;br /&gt;&lt;br /&gt;All 8 sounds in the drum kit can be played at the same time. Each beat is played if the opacity of the drum element is .6 or greater. Here is the code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;public void Play()&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;     Background = new SolidColorBrush(Colors.Black);&lt;br /&gt;&lt;br /&gt;     for (int i = 0; i &amp;lt; 8; i++)&lt;br /&gt;&lt;br /&gt;     {&lt;br /&gt;&lt;br /&gt;          Ellipse oEllipse = Children[i] as Ellipse;&lt;br /&gt;&lt;br /&gt;          if (oEllipse.Opacity &amp;lt; .6)&lt;br /&gt;&lt;br /&gt;          continue;&lt;br /&gt;&lt;br /&gt;          StreamResourceInfo oInfo = Sounds[i];&lt;br /&gt;&lt;br /&gt;          MediaElement oElement = Elements[i];&lt;br /&gt;&lt;br /&gt;          oElement.SetSource(oInfo.Stream);&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I used the threshold value of .6 on opacity because I wanted to make it possible to write multiple math expressions that, if applied to the same section of the beat, could cancel or enhance the pattern already in place.&lt;br /&gt;&lt;br /&gt;To do this I used 2 techniques. The first was a lambda expression:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;KitAction(0, xx =&amp;gt; (xx % 16) == 1); //Crash every 16 beat&lt;br /&gt;&lt;br /&gt;KitAction(4, xx =&amp;gt; (xx % 4) == 1); //snare every 4 beats&lt;br /&gt;&lt;br /&gt;public void KitAction(int iIndex, Func&amp;lt;int,bool&amp;gt; oOnFunction)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;     for (int i = 0; i &amp;lt; MaxCount; i++)&lt;br /&gt;&lt;br /&gt;     {&lt;br /&gt;&lt;br /&gt;          double dValue = oOnFunction(i) ? 1.0 : 0.1;&lt;br /&gt;&lt;br /&gt;          BlendBeat(iIndex, i, dValue);&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Using the lambda expression lets you describe a beat pattern with a simple rule; it lays down the basic beat for a complete song.&lt;br /&gt;&lt;br /&gt;Fill patterns are not as regular, so I created an API to describe them with a string of X's and Spaces:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;BlendBeat(6, 0, "XXX XX XXX XXXXXXXX XX"); //Tom2 fill from opening&lt;br /&gt;&lt;br /&gt;BlendBeat(7, 0, "XXX X XXX XX XXXXX X"); //Tom3 fill from opening&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public int BlendBeat(int iIndex, int i, string sMask)&lt;br /&gt;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;     for (int j = 0; j &amp;lt;= sMask.Length-1; j++)&lt;br /&gt;&lt;br /&gt;     {&lt;br /&gt;&lt;br /&gt;          double dValue = sMask[j] == ' ' ? 0.0 : 1.0;&lt;br /&gt;&lt;br /&gt;          try&lt;br /&gt;&lt;br /&gt;          {&lt;br /&gt;&lt;br /&gt;               KitPanel oKit = Children[i + j] as KitPanel;&lt;br /&gt;&lt;br /&gt;               oKit.BlendBeat(iIndex, dValue);&lt;br /&gt;&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          catch&lt;br /&gt;&lt;br /&gt;          {&lt;br /&gt;&lt;br /&gt;               return -1;&lt;br /&gt;&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return i + sMask.Length;&lt;br /&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the process of building this example, I documented four "A-Ha" moments about custom panels and media elements. These are things that took longer then they should have until I learned the tricks and tips of Silverlight development. I will explain them in parts 2 and 3.&lt;br /&gt;&lt;br /&gt;The complete source code for beat box can be downloaded here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://drumpanel.codeplex.com/"&gt;http://drumpanel.codeplex.com/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2232229645767964714?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2232229645767964714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2232229645767964714&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2232229645767964714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2232229645767964714'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/beat-box-application-part-1-overview.html' title='Beat Box Application - Part 1  overview'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_s1N_RQkyQXU/SfTYjuktVNI/AAAAAAAAABw/CHKo4LVCfhM/s72-c/BeatLayout.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-4616740059031893923</id><published>2009-04-24T13:05:00.003-04:00</published><updated>2009-06-09T11:20:03.373-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='loops'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='lists'/><title type='text'>Looping Over Lists</title><content type='html'>Here is a very common way to define a list of instances in .NET (in this example, a list of particles):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;List&amp;lt;Particle&amp;gt; Particles = new List&amp;lt;Particle&amp;gt;();&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;There is a really good video on animation that includes the creation and application of particle emitters at this link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://videos.visitmix.com/MIX09/T12F"&gt;http://videos.visitmix.com/MIX09/T12F&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The demo on Particles is about halfway through.&lt;br /&gt;&lt;br /&gt;Also you can try an example created by Robby at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://labs.nerdplusart.com/particles/fullscreen.php"&gt;http://labs.nerdplusart.com/particles/fullscreen.php&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There are at least two ways you can loop through all the elements in a list -- a For loop and a ForEach loop. A For loop would look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;for (int i=0; i&amp;lt;Particles.count; i++)&lt;br /&gt;{&lt;br /&gt;     var oParticle=Particles[i];&lt;br /&gt;     if ( oParticle.Age &amp;gt; oParticle.LifeTime)&lt;br /&gt;     {&lt;br /&gt;          LayoutRoot.Children.Remove(oParticle);&lt;br /&gt;          Particles.Remove(oParticle);&lt;br /&gt;     }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;When I first did my implementation I used a ForEach loop, because I always use a ForEach -- the coding is simpler:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;foreach (Particle oParticle in Particles)&lt;br /&gt;     if ( oParticle.Age &amp;gt; oParticle.LifeTime)&lt;br /&gt;     {&lt;br /&gt;          LayoutRoot.Children.Remove(oParticle);&lt;br /&gt;          Particles.Remove(oParticle);&lt;br /&gt;     }&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In both cases the loop is (sooner or later) going to try to remove a particle object from the collection you are looping over. Removing it from the LayoutRoot.Children is never a problem because this connection is not currently locked by the loop, but calling Particles.Remove(oParticle) is a problem in the ForEach loop because the Particles collection is locked from editing (adds and removes) during the ForEach loop.&lt;br /&gt;&lt;br /&gt;My first fix was to make a copy of the collection I was looping over. This is a bad idea because it really slows things down, and in a graphics animation, you need all the speed you can get.&lt;br /&gt;&lt;br /&gt;So I went back and tried the For loop and realized why the experts selected that implementation. Even though the &lt;em&gt;i&lt;/em&gt;th item is removed from the list, the collection does not automatically close up ranks and reindex all the items. Being aware of this distinction is extremely useful in certain applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-4616740059031893923?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/4616740059031893923/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=4616740059031893923&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/4616740059031893923'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/4616740059031893923'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/looping-over-lists.html' title='Looping Over Lists'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2030723556471944654</id><published>2009-04-11T11:57:00.015-04:00</published><updated>2009-06-09T11:20:03.373-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IValueConverter'/><category scheme='http://www.blogger.com/atom/ns#' term='binding'/><category scheme='http://www.blogger.com/atom/ns#' term='VisualStateManager'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Binding a State Change to a Property Change</title><content type='html'>The video below describes the application in which we applied the approach described in this blog post:&lt;br /&gt;&lt;br /&gt;&lt;object width="578" height="522" class="BLOG_video_class" id="BLOG_video-79d284bc6be08771" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v21.nonxt3.googlevideo.com/videoplayback?id%3D79d284bc6be08771%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D669639269724804248C3C7505B40672658D11D2.F870CB580D33D19F4C3D179D825B2DBCB55E89D%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D79d284bc6be08771%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dh67BTcZULPs9_N7wNiiDWMUe4qA&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="578" height="522" bgcolor="#FFFFFF"flashvars="flvurl=http://v21.nonxt3.googlevideo.com/videoplayback?id%3D79d284bc6be08771%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D669639269724804248C3C7505B40672658D11D2.F870CB580D33D19F4C3D179D825B2DBCB55E89D%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D79d284bc6be08771%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dh67BTcZULPs9_N7wNiiDWMUe4qA&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;VisualStateManager is a great way to change a lot of properties at once when the state of the model that is bound to the control changes. It allows you to separate design from implementation and gives your designers freedom to build some really interesting visual applications.&lt;br /&gt;The code for forcing a Silverlight control to change state is:&lt;br /&gt;&lt;br /&gt;VisualStateManager.GoToState(oControl, "NEWSTATE", true);&lt;br /&gt;&lt;br /&gt;So you need to call this code to force a state transition. But what if you want to notify VisualStateManager based on the change of a value in your domain model? You can exploit the IValueConverter interface and the normal binding mechanism to do this.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;void OnLoaded(object sender, RoutedEventArgs e)&lt;br /&gt;{&lt;br /&gt;     Binding oBinding = new Binding("DisplayState");&lt;br /&gt;     oBinding.Converter = StateConverter;&lt;br /&gt;     oBinding.ConverterParameter = ValueIcon;&lt;br /&gt;     //the control that is the target of the state change&lt;br /&gt;     LayoutRoot.SetBinding(FrameworkElement.VisibilityProperty, oBinding);&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;When the control is loaded I use standard binding to associate the VisibilityProperty of the control to the property in my domain model named "DisplayState". The binding instructions include the StateConverter (defined next), and the value of ConverterParameter is the XAML element that is the target of the GoToState Command. As you can see, the StateConverter ignores the conversion completely and always returns 'visible'. However, during the update process, the control passed in the parameter argument is now the target of the GoToState command. Furthermore, the new state is set to the value calculated by the property bound to this StateConverter. Whenever the domain model changes state, the GoToState will be targeted at the associated control and passed the correct value.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;public class StateConverter : ValueConverter&lt;br /&gt;{&lt;br /&gt;     #region IValueConverter Members&lt;br /&gt;&lt;br /&gt;     public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)&lt;br /&gt;     {&lt;br /&gt;          Control oControl = parameter as Control;&lt;br /&gt;          sState = value.ToString();&lt;br /&gt;          VisualStateManager.GoToState(oControl, sState, true);&lt;br /&gt;          return Visibility.Visible;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     #endregion&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;I like to have all my converter classes inherit from a common converter class, mainly because in most cases the conversions do not require a ConvertBack method -- this way I only need to implement the functionality the converter truly requires.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;public class ValueConverter : IValueConverter&lt;br /&gt;{&lt;br /&gt;     #region IValueConverter Members&lt;br /&gt;&lt;br /&gt;     public virtual object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)&lt;br /&gt;     {&lt;br /&gt;          return value;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     public virtual object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)&lt;br /&gt;     {&lt;br /&gt;          return value;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     #endregion&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2030723556471944654?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=79d284bc6be08771&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2030723556471944654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2030723556471944654&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2030723556471944654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2030723556471944654'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/binding-state-change-to-property-change.html' title='Binding a State Change to a Property Change'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-8633248407481052364</id><published>2009-04-11T11:44:00.005-04:00</published><updated>2009-06-09T11:20:03.374-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='custom panel'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='visio'/><title type='text'>Replicating a Visio Page Using a Silverlight Panel - Part II</title><content type='html'>The arrange method can be modified to account for the object being positioned so that the center of rotation is exactly at the pin location.&lt;br /&gt;&lt;br /&gt;Under the covers, the Visio shape sheet uses four other cells to render the shape's positioning transform -- Width, Height, LocPinX and LocPinY. This can be managed in the following function LocalPin():&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;        public virtual void DoArrange(Size finalSize)&lt;br /&gt;        {&lt;br /&gt;            foreach (UIElement oChild in Children)&lt;br /&gt;            {&lt;br /&gt;                double dX = (double)oChild.GetValue(SketchPanel.PinXProperty);&lt;br /&gt;                double dY = (double)oChild.GetValue(SketchPanel.PinYProperty);&lt;br /&gt;                double dAngle = (double)oChild.GetValue(SketchPanel.AngleProperty);&lt;br /&gt;                Point oLocal = (Point)LocalPin(oChild);&lt;br /&gt;&lt;br /&gt;                dX -= oLocal.X;&lt;br /&gt;                dY -= oLocal.Y;&lt;br /&gt;                Point oPoint = new Point(dX, dY);&lt;br /&gt;                SetRenderTransform(oChild, dAngle, oPoint);&lt;br /&gt;&lt;br /&gt;                oChild.Arrange(new Rect(0, 0, oChild.DesiredSize.Width, oChild.DesiredSize.Height));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        public Point LocalPin(UIElement oChild)&lt;br /&gt;        {&lt;br /&gt;            double dWidth = (double)oChild.GetValue(SketchPanel.WidthProperty);&lt;br /&gt;            double dHeight = (double)oChild.GetValue(SketchPanel.HeightProperty);&lt;br /&gt;            Point oOrigin = (Point)oChild.GetValue(SketchPanel.RenderTransformOriginProperty);&lt;br /&gt;&lt;br /&gt;            double dLocPinX = double.NaN.Equals(dWidth) ? 0.0 : dWidth * oOrigin.X;&lt;br /&gt;            double dLocPinY = double.NaN.Equals(dHeight) ? 0.0 : dHeight * oOrigin.Y;&lt;br /&gt;            return new Point(dLocPinX, dLocPinY);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-8633248407481052364?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/8633248407481052364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=8633248407481052364&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8633248407481052364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8633248407481052364'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/replicating-visio-page-using_11.html' title='Replicating a Visio Page Using a Silverlight Panel - Part II'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-4260015157021075325</id><published>2009-04-11T11:28:00.006-04:00</published><updated>2009-06-09T11:20:03.374-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='custom panel'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='visio'/><title type='text'>Replicating a Visio Page Using a Silverlight Panel</title><content type='html'>The shape model in Visio simplifies the location of the shape into 3 ShapeSheet cells: PinX, PinY and Angle. This is all you need to drop a shape on a page and rotate it.&lt;br /&gt;&lt;br /&gt;It is possible to create a Silverlight custom panel, using attached properties that position XAML elements using the Visio PinX, PinY analogy. Sometimes this is easier than using the Top Left position commands associated with the Silverlight canvas:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;        #region Attached Properties  PinX  PinY  Angle&lt;br /&gt;        public static double GetPinX(DependencyObject obj)&lt;br /&gt;        {&lt;br /&gt;            return (double)obj.GetValue(PinXProperty);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static void SetPinX(DependencyObject obj, double value)&lt;br /&gt;        {&lt;br /&gt;            obj.SetValue(PinXProperty, value);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Using a DependencyProperty as the backing store for PinX.  This enables animation, styling, binding, etc...&lt;br /&gt;        public static readonly DependencyProperty PinXProperty =&lt;br /&gt;            DependencyProperty.RegisterAttached("PinX",&lt;br /&gt;            typeof(double),&lt;br /&gt;            typeof(SketchPanel),&lt;br /&gt;            new PropertyMetadata(0.0, new PropertyChangedCallback(OnPinXChanged)));&lt;br /&gt;&lt;br /&gt;        protected static void OnPinXChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)&lt;br /&gt;        {&lt;br /&gt;            SketchPanel oPanel = obj as SketchPanel;&lt;br /&gt;            if (oPanel != null)&lt;br /&gt;                oPanel.InvalidateArrange();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        public static double GetPinY(DependencyObject obj)&lt;br /&gt;        {&lt;br /&gt;            return (double)obj.GetValue(PinYProperty);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static void SetPinY(DependencyObject obj, double value)&lt;br /&gt;        {&lt;br /&gt;            obj.SetValue(PinYProperty, value);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Using a DependencyProperty as the backing store for PinY.  This enables animation, styling, binding, etc...&lt;br /&gt;        public static readonly DependencyProperty PinYProperty =&lt;br /&gt;            DependencyProperty.RegisterAttached("PinY",&lt;br /&gt;            typeof(double),&lt;br /&gt;            typeof(SketchPanel),&lt;br /&gt;            new PropertyMetadata(0.0, new PropertyChangedCallback(OnPinYChanged)));&lt;br /&gt;&lt;br /&gt;        protected static void OnPinYChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)&lt;br /&gt;        {&lt;br /&gt;            SketchPanel oPanel = obj as SketchPanel;&lt;br /&gt;            if (oPanel != null)&lt;br /&gt;                oPanel.InvalidateArrange();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        public static double GetAngle(DependencyObject obj)&lt;br /&gt;        {&lt;br /&gt;            return (double)obj.GetValue(AngleProperty);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static void SetAngle(DependencyObject obj, double value)&lt;br /&gt;        {&lt;br /&gt;            obj.SetValue(AngleProperty, value);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Using a DependencyProperty as the backing store for Angle.  This enables animation, styling, binding, etc...&lt;br /&gt;        public static readonly DependencyProperty AngleProperty =&lt;br /&gt;            DependencyProperty.RegisterAttached("Angle",&lt;br /&gt;            typeof(double),&lt;br /&gt;            typeof(SketchPanel),&lt;br /&gt;            new PropertyMetadata(0.0, new PropertyChangedCallback(OnAngleChanged)));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        protected static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)&lt;br /&gt;        {&lt;br /&gt;            SketchPanel oPanel = obj as SketchPanel;&lt;br /&gt;            if (oPanel != null)&lt;br /&gt;                oPanel.InvalidateArrange();&lt;br /&gt;        }&lt;br /&gt;        #endregion&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Once you have defined the attachment properties on the panel, you can use these to lay things out in the arrange method:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;        protected override Size ArrangeOverride(Size finalSize)&lt;br /&gt;        {&lt;br /&gt;            DoArrange(finalSize);&lt;br /&gt;            return base.ArrangeOverride(finalSize);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        public virtual void DoArrange(Size finalSize)&lt;br /&gt;        {&lt;br /&gt;            foreach (UIElement oChild in Children)&lt;br /&gt;            {&lt;br /&gt;                double dX = (double)oChild.GetValue(SketchPanel.PinXProperty);&lt;br /&gt;                double dY = (double)oChild.GetValue(SketchPanel.PinYProperty);&lt;br /&gt;                double dAngle = (double)oChild.GetValue(SketchPanel.AngleProperty);&lt;br /&gt;&lt;br /&gt;                Point oPoint = new Point(dX, dY);&lt;br /&gt;                SetRenderTransform(oChild, dAngle, oPoint);&lt;br /&gt;&lt;br /&gt;                oChild.Arrange(new Rect(0, 0, oChild.DesiredSize.Width, oChild.DesiredSize.Height));&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        internal TransformGroup SetRenderTransform(UIElement oControl, double dAng, Point pTrans)&lt;br /&gt;        {&lt;br /&gt;            if (!(oControl.RenderTransform is TransformGroup))&lt;br /&gt;                oControl.RenderTransform = new TransformGroup();&lt;br /&gt;&lt;br /&gt;            TransformGroup oGroup = oControl.RenderTransform as TransformGroup;&lt;br /&gt;            if (oGroup.Children.Count == 0)&lt;br /&gt;            {&lt;br /&gt;                oGroup.Children.Add(new RotateTransform());&lt;br /&gt;                oGroup.Children.Add(new TranslateTransform());&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            RotateTransform oRotate = oGroup.Children[0] as RotateTransform;&lt;br /&gt;            oRotate.Angle = dAng;&lt;br /&gt;&lt;br /&gt;            TranslateTransform oTranslate = oGroup.Children[1] as TranslateTransform;&lt;br /&gt;            oTranslate.X = pTrans.X;&lt;br /&gt;            oTranslate.Y = pTrans.Y;&lt;br /&gt;&lt;br /&gt;            return oGroup;&lt;br /&gt;        }&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;In the next post we will explore extending the model to be even more Visio-like, using LocPinX and LocPinY, height and width.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-4260015157021075325?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/4260015157021075325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=4260015157021075325&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/4260015157021075325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/4260015157021075325'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/replicating-visio-page-using.html' title='Replicating a Visio Page Using a Silverlight Panel'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-8739946117282081639</id><published>2009-04-06T09:04:00.015-04:00</published><updated>2009-06-09T11:20:03.374-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mouse move'/><category scheme='http://www.blogger.com/atom/ns#' term='trigonometry'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='rendertransform'/><title type='text'>Using the Mouse to Rotate a Silverlight Element</title><content type='html'>Steve: I was asked on two separate occasions, during interviews, programming problems that involved geometry -- in other words, could I work with sin, cos and tan to calculate geometry. This is something I learned in 8th grade and I have used this knowledge in many applications, but this demo is probably the most fun.&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_s1N_RQkyQXU/SeHW7jd6l0I/AAAAAAAAAA0/omFSd3Ulu3Y/s1600-h/Transforms_Controls_Turret.png"&gt;&lt;/a&gt;&lt;br /&gt;The goal of this demo, as explained in the video below, is to build a targeting system that uses mouse movement to direct the projectiles.&lt;br /&gt;&lt;br /&gt;&lt;object width="567" height="452" class="BLOG_video_class" id="BLOG_video-4e3a0c984254955c" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v15.nonxt1.googlevideo.com/videoplayback?id%3D4e3a0c984254955c%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D2A29E4D4F618DAB313F3AEB55D96C294B81C245B.1BDAADB0913EAA901463AE522E99C077E73358F1%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D4e3a0c984254955c%26offsetms%3D5000%26itag%3Dw160%26sigh%3DKDzVXCE5Qh-uktVdKDigiGtpjL4&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="567" height="452" bgcolor="#FFFFFF"flashvars="flvurl=http://v15.nonxt1.googlevideo.com/videoplayback?id%3D4e3a0c984254955c%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1330190913%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D2A29E4D4F618DAB313F3AEB55D96C294B81C245B.1BDAADB0913EAA901463AE522E99C077E73358F1%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D4e3a0c984254955c%26offsetms%3D5000%26itag%3Dw160%26sigh%3DKDzVXCE5Qh-uktVdKDigiGtpjL4&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The XAML in the tank control needs to represent the turret separate from the body of the tank; Deb has used Expression Blend to create a transform group that lets the turret rotate separately from the tank.&lt;br /&gt;&lt;br /&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 277px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5323774116115630338" border="0" alt="" src="http://3.bp.blogspot.com/_s1N_RQkyQXU/SeHYWh99yQI/AAAAAAAAAA8/FHDaaJd2Ojg/s400/Transforms_Controls_Turret.png" /&gt;&lt;br /&gt;&lt;br /&gt;Now it is time to overlay the math on the geometry:&lt;br /&gt;&lt;br /&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 400px; DISPLAY: block; HEIGHT: 306px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5323774517755921074" border="0" alt="" src="http://1.bp.blogspot.com/_s1N_RQkyQXU/SeHYt6MeQrI/AAAAAAAAABE/DYa05hcqbSo/s400/Tank_Game+math.png" /&gt;&lt;br /&gt;&lt;br /&gt;Call the code below every time the mouse moves; the variables synchronize with the picture:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;e.GetPosition(oElement).X and e.GetPosition(oElement).Y get the current position&lt;br /&gt;of the mouse in the coordinate system of the canvas.&lt;br /&gt;&lt;br /&gt;oControl is the user control that is the tank on the screen, so oSize is the height and width of the tank, and oPoint is where the center of the tank is relative to the top-left corner and is used to position it on the canvas.&lt;br /&gt;&lt;br /&gt;TranslationX and TranslationY is current location of the tank's top-left corner on the canvas, and TranslationAngle is the direction it is heading. &lt;/blockquote&gt;&lt;br /&gt;Now that math. Dx an Dy represent the distance along the X and Y axes from the center of the tank to the current mouse location. The calculations are done in the coordinate system of the canvas.&lt;br /&gt;&lt;br /&gt;The radius or hypotenuse of the triangle is calculated and then divided into Dx and Dy to normalize the values. Then the ArcTan is calculated to determine the angle.&lt;br /&gt;&lt;br /&gt;One final trick. Remember from the first diagram that the rotation of the turret is relative to the body of the tank. To orient the gun so it points at the mouse, you must subtract the calculated angle from the direction the tank is traveling.&lt;br /&gt;&lt;br /&gt;Call the code below when the mouse is moved:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;////virtual method that lets any game element fire a weapon&lt;br /&gt;public virtual bool TrackMouse(Canvas oElement, Control oControl, MouseEventArgs e)&lt;br /&gt;{&lt;br /&gt;     Size oSize = oControl.RenderSize;&lt;br /&gt;     Point oPoint = oControl.RenderTransformOrigin;&lt;br /&gt;&lt;br /&gt;     //some basic trig&lt;br /&gt;     double dX = e.GetPosition(oElement).X - TranslationX + oPoint.X * oSize.Width;&lt;br /&gt;     double dY = TranslationY + oPoint.Y * oSize.Height - e.GetPosition(oElement).Y;&lt;br /&gt;     double dRadius = Math.Sqrt(dX * dX + dY * dY);&lt;br /&gt;&lt;br /&gt;     //remember WPF wants angles in degrees&lt;br /&gt;     double dAngle = System.Math.Atan2(dY / dRadius, dX / dRadius) * 180.0 / System.Math.PI;&lt;br /&gt;     dAngle %= 360.0;&lt;br /&gt;&lt;br /&gt;     //the virtual SetFireAngle method is used to control the turret&lt;br /&gt;     //this code is here to account for the direction the tank is heading (i.e. Player.TranslationAngle)&lt;br /&gt;     //allowing the tank to move in one direction and shoot in another&lt;br /&gt;     SetFireAngle(TranslationAngle - dAngle);&lt;br /&gt;     return false;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-8739946117282081639?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=4e3a0c984254955c&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/8739946117282081639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=8739946117282081639&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8739946117282081639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/8739946117282081639'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/using-mouse-to-rotate-silverlight.html' title='Using the Mouse to Rotate a Silverlight Element'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_s1N_RQkyQXU/SeHYWh99yQI/AAAAAAAAAA8/FHDaaJd2Ojg/s72-c/Transforms_Controls_Turret.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-1717616621079701669</id><published>2009-04-03T09:42:00.029-04:00</published><updated>2009-06-09T11:20:03.374-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='drag and drop'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='visual tree'/><title type='text'>How To Do Drag &amp; Drop Using the Visual Tree</title><content type='html'>First, a shout out to Jesse Liberty who has a great post on the basic Drag &amp;amp; Drop pattern:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.silverlight.net/blogs/jesseliberty/archive/2009/01/13/drag-and-drop-with-managed-code.aspx"&gt;http://www.silverlight.net/blogs/jesseliberty/archive/2009/01/13/drag-and-drop-with-managed-code.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When creating a complex application, I have found that attaching a MouseLeftButtonDown, MouseMove and MouseLeftButtonUp to every object that is dragable is problematic. As an alternative, I use the function &lt;strong&gt;VisualTreeHelper.FindElementsInHostCoordinates&lt;/strong&gt; and manage the process from a parent UI element.&lt;br /&gt;&lt;br /&gt;This code sets up mouse up and mouse down events for the parent UI object:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;        &lt;br /&gt;public DrawingSurface() : base()&lt;br /&gt;{&lt;br /&gt;     MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);&lt;br /&gt;     MouseLeftButtonUp += new MouseButtonEventHandler(OnMouseLeftButtonUp);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;The following code lets me hit test against the children objects in the entire VisualTree, looking for an element of type "T", which are UIElements. During the search I am also looking for a panel of type "C", just in case the user is not over an object (for example, selecting nothing). A list of select objects is returned :&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;        &lt;br /&gt;public List&amp;lt;T&amp;gt; FindElement&amp;ltT,C&amp;gt;(Point oPoint, ref Panel oPanel) where T : UIElement&lt;br /&gt;{&lt;br /&gt;     List&amp;ltT&amp;gt; oList = new List&amp;ltT&amp;gt;();&lt;br /&gt;     foreach (UIElement oElement in VisualTreeHelper.FindElementsInHostCoordinate(oPoint, this))&lt;br /&gt;     {&lt;br /&gt;          T oShape = oElement as T;&lt;br /&gt;          if (oShape != null)&lt;br /&gt;               oList.Add(oShape);&lt;br /&gt;&lt;br /&gt;          if (oElement is C &amp;amp;&amp;amp; oPanel == null)&lt;br /&gt;               oPanel = oElement as Panel;&lt;br /&gt;     }&lt;br /&gt;     return oList;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;Here is just one example of some of the hit test logic you can implement. Based on the type of SketchObject that is found, I can infer the user's drawing need -- is the user planning to drag the shape, stretch the shape, connect the shape, or create the shape -- and auto-select the right drawing tool. It is a lot easier to implement this logic in the parent UI Element:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;        &lt;br /&gt;void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)&lt;br /&gt;{&lt;br /&gt;     Panel oPanel = null;&lt;br /&gt;     Point oPoint = e.GetPosition(null);&lt;br /&gt;&lt;br /&gt;     CurrentTool = DrawingTool.Ignore;&lt;br /&gt;&lt;br /&gt;     ActiveHandle = FindElement&lt;sketchhandle,&gt;(oPoint, ref oPanel);&lt;br /&gt;     if (ActiveHandle.Count != 0)&lt;br /&gt;     {&lt;br /&gt;          if (ActiveHandle[0] is RotateHandle)&lt;br /&gt;               CurrentTool = DrawingTool.Rotate;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     ActivePort = FindElement&lt;sketchport,&gt;(oPoint,ref oPanel);&lt;br /&gt;     if (ActivePort.Count != 0)&lt;br /&gt;     {&lt;br /&gt;          if (CurrentTool == DrawingTool.Ignore)&lt;br /&gt;               CurrentTool = DrawingTool.Connect;&lt;br /&gt;&lt;br /&gt;          OpenDragConnect(ActivePort[0], oPoint);&lt;br /&gt;          return;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     ActiveGroup = FindElement&lt;sketchshape,&gt;(oPoint, ref oPanel);&lt;br /&gt;     if(ActiveGroup.Count != 0)&lt;br /&gt;     {&lt;br /&gt;          if ( CurrentTool == DrawingTool.Ignore )&lt;br /&gt;               CurrentTool = DrawingTool.Move;&lt;br /&gt;&lt;br /&gt;          OpenDragDropShape(ActiveGroup[0],oPoint);&lt;br /&gt;          return;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     ActiveMaster = FindElement&lt;sketchmaster,&gt;(oPoint, ref oPanel);&lt;br /&gt;     if (ActiveMaster.Count != 0)&lt;br /&gt;     {&lt;br /&gt;          CurrentTool = DrawingTool.Create;&lt;br /&gt;          OpenDragDropShape(ActiveMaster[0], oPoint);&lt;br /&gt;          return;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;By using this approach you can consolidate all of drag &amp; drop code in one place, making it easier to manage and maintain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-1717616621079701669?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/1717616621079701669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=1717616621079701669&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/1717616621079701669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/1717616621079701669'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/how-to-do-drag-drop-using-visual-tree.html' title='How To Do Drag &amp; Drop Using the Visual Tree'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-5073287929615159987</id><published>2009-04-03T09:17:00.025-04:00</published><updated>2009-06-09T11:20:03.374-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='zoom'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='mouse wheel'/><title type='text'>How to Zoom In and Out with a Mouse Wheel in Silverlight</title><content type='html'>A known fact about Silverlight is that it does not currently listen to the mouse wheel; there are no events in XAML that return its status.  The following code will allow you to monitor the mouse wheel by using events passed by the browser, and zoom in and out when the mouse wheel is turned. &lt;br /&gt;&lt;br /&gt;The first section of code sets up Silverlight to listen to the browser for the OnMouseWheel event:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;        &lt;br /&gt;private void OnMouseWheel(object sender, HtmlEventArgs args)&lt;br /&gt;{&lt;br /&gt;     HtmlPage.Window.AttachEvent("DOMMouseScroll", OnMouseWheel);&lt;br /&gt;     HtmlPage.Window.AttachEvent("onmousewheel", OnMouseWheel);&lt;br /&gt;     HtmlPage.Document.AttachEvent("onmousewheel", OnMouseWheel);&lt;br /&gt;} &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;This next piece of code gets the delta for the mouse wheel, positive or negative.  We don't care how much the wheel has turned, only if it was up/forward/positive or down/back/negative, translating this into a +1 or -1:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;        &lt;br /&gt;private void OnMouseWheel(object sender, HtmlEventArgs args)&lt;br /&gt;{&lt;br /&gt;      double mouseDelta = 0;&lt;br /&gt;      ScriptObject e = args.EventObject;&lt;br /&gt;&lt;br /&gt;      // Mozilla and Safari   &lt;br /&gt;      if (e.GetProperty("detail") != null)&lt;br /&gt;      {&lt;br /&gt;           mouseDelta = ((double)e.GetProperty("detail"));&lt;br /&gt;      }&lt;br /&gt;      // IE and Opera   &lt;br /&gt;      else if (e.GetProperty("wheelDelta") != null)&lt;br /&gt;      mouseDelta = ((double)e.GetProperty("wheelDelta"));&lt;br /&gt;&lt;br /&gt;      double dSign = Math.Sign(mouseDelta);&lt;br /&gt;      //now change the scale of the activePage xaml element&lt;br /&gt;      //this is typically a canvas this is a child of the local root&lt;br /&gt;      ChangeScale(ActivePage, dSign);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;The last piece of code uses this number to calculate and apply a scaling factor to the target XAML element.&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-size:85%;"&gt;  &lt;br /&gt;private void ChangeScale(FrameworkElement oTarget, double dSign)&lt;br /&gt;       &lt;br /&gt;{&lt;br /&gt;     if(!(oTarget.RenderTransform is TransformGroup))&lt;br /&gt;     oTarget.RenderTransform = new TransformGroup();&lt;br /&gt;&lt;br /&gt;     TransformGroup oGroup = oTarget.RenderTransform as TransformGroup;&lt;br /&gt;     if (oGroup.Children.Count == 0)          &lt;br /&gt;     {              &lt;br /&gt;          oGroup.Children.Add(new ScaleTransform());&lt;br /&gt;          oTarget.RenderTransformOrigin = new Point(.5, .5);          &lt;br /&gt;     }&lt;br /&gt;            &lt;br /&gt;     m_dCurrentZoom += 0.1 * dSign;&lt;br /&gt;&lt;br /&gt;     ScaleTransform oScale = oGroup.Children[0] as ScaleTransform;&lt;br /&gt;     oScale.ScaleX = m_dCurrentZoom;&lt;br /&gt;     oScale.ScaleY = m_dCurrentZoom;     &lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;This code sets the focal point of the zoom to the center (.5, .5) of the XAML element that is passed in the function, typically a canvas.  If you wanted to zoom in on something that is drawn on the canvas, like a shape or a button, you would need to calculate where that element is relative to the total width and height of the canvas (e.g. 30% of x, 70% of y = .3, .7).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-5073287929615159987?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/5073287929615159987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=5073287929615159987&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5073287929615159987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/5073287929615159987'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/how-to-zoom-in-and-out-with-mousewheel.html' title='How to Zoom In and Out with a Mouse Wheel in Silverlight'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-2552019781450623211</id><published>2009-04-01T12:00:00.009-04:00</published><updated>2009-06-09T11:20:03.375-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visibility'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='opacity'/><title type='text'>Behaviors and Uses of Collapsed vs. Zero Opacity</title><content type='html'>While visually, setting a XAML element's opacity to zero is the same as setting visibility to collapsed, the two have different behaviors when it comes to detecting interaction with the mouse. An element whose visibility is set to 'collapsed' is undetectable by a mouse; it is as if the element has been removed from the visual tree. Setting an element's opacity to zero, however, makes it invisible while it is still detectable by the mouse, e.g. a button with zero opacity is still clickable.&lt;br /&gt;&lt;br /&gt;This distinction is useful in a number of ways. One application is creating an invisible button on a page that the knowledgeable user can click to trigger a desired action such as debugging or a special report. To do this, you would create a button with opacity equal to zero. Conversely, you may have a button you wish to deactivate as well as hide, in which case you would set visibility to collapsed.&lt;br /&gt;&lt;br /&gt;Another application of zero opacity is to create a shield which allows lower level elements to display but renders them inactive - for example, you may want to do this during an asynchronous operation like retrieving an RSS feed, during which you want to prevent user interaction. In this case, you could create a large rectangle covering the page but set its opacity to zero -- this would allow the user to see what is happening underneath but prevents them from doing anything. When the asynchronous event is complete, the rectangle could then be collapsed to allow user interaction.&lt;br /&gt;&lt;br /&gt;Opacity and visibility are also be different in their use for visualization, especially during animations. Opacity is a continuous value that ranges from 0 to 100% in Blend or 0 to 1 in XAML, making it a good candidate for animations, where an element can move from one value to another during a given timeframe. Visibility is an on/off value, either visible or collapsed, and changes at one point in time. These differences in visualization, combined with differences in mouse interaction, should be considered by the designer/developer when choosing between the two properties.&lt;br /&gt;&lt;br /&gt;The most important thing to remember is just because you can't see it, doesn't mean you can't click it! An element whose opacity = 0 can still be an active control on your Silverlight application. If you want something to be really 'gone', set its visiblity to collapsed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-2552019781450623211?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/2552019781450623211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=2552019781450623211&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2552019781450623211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/2552019781450623211'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/behaviors-and-uses-of-collapsed-vs-zero.html' title='Behaviors and Uses of Collapsed vs. Zero Opacity'/><author><name>Steve Strong</name><uri>http://www.blogger.com/profile/11099381810874609171</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_x0fXcQg3teU/SdOIQ--fcjI/AAAAAAAAAAY/8DTS76IcMIc/S220/n776802961_3349.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6088992123466333517.post-6344891680508699842</id><published>2009-04-01T10:26:00.001-04:00</published><updated>2009-06-09T11:20:03.375-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='visio'/><title type='text'>Sharing What We've Learned about Silverlight</title><content type='html'>DEB:&lt;br /&gt;We’ve always been very big on visualization.  The complex applications we’ve built and deployed as Apprentice Systems made extensive use of Microsoft Visio for knowledge capture, diagramming and drawing generation; we’ve even used interactive 3D successfully.  But nothing has excited us as much as Silverlight.&lt;br /&gt;&lt;br /&gt;With Silverlight we get two things our customers have consistently asked for:  compelling visuals and web-based deployment.  Our use of Visio required that we stay on the desktop, but increasingly customers have been demanding solutions that run inside a browser.  Also, big upfront licensing fees are getting increasingly difficult to sell; software as a service is the business model that fits our tough economic times.  Silverlight is a perfect fit for the direction we wanted to take our business.&lt;br /&gt;&lt;br /&gt;But it’s also a great fit for the way we work, because I do most of the design work, and Steve is the developer.  I handle everything Adobe and FrontPage, do most of the Visio shape work, and know next to nothing about .NET and C#.  We used to pass things back and forth A LOT, interrupting the workflow, waiting for a project to return for my input, then handing it off again.  The move to Silverlight and Expression Blend has made me more self sufficient, and from what I’ve seen of Blend 3, I’ll be even more so in the future.  Also, the integration of Photoshop and Illustrator will really unleash creativity as control skinning gets much, much easier.  I can’t wait to get my hands on a version of Blend that has all the new features, including SketchFlow!&lt;br /&gt;&lt;br /&gt;STEVE:&lt;br /&gt;I have learned Silverlight by reading a lot of blogs and watching hours of video.  I feel like I have attended Mix07, Mix08, Mix09 and PCD08 from the web coverage.   I have been learning from the bloggers and tweeting with the Twitters:  Jesse Liberty, Tim Heuer, Shawn Wildermuth, Mike Snow, Brad Abrams, Nikhil Kothari, Jeff Wilcox, John Papa, Tim Sneath, Scorbs (Karen Corby),  Shawn Oster, Erik Mork, John Stockton, Joe Stegman, Laurence Moroney, &amp;amp; Scott Gu.&lt;br /&gt;&lt;br /&gt;Silverlight.net is my home page, and I bought an iPod to listen to shows like Sparkling Client, .NET Rocks, Herding Code, and Stack Overflow. &lt;br /&gt;&lt;br /&gt;The writing is on the wall and you can see it in the Silverlight 3 and Blend 3 Betas -- this is a platform that is going to change how many people will think about software and the web.  &lt;br /&gt;&lt;br /&gt;In the past year we have completed five significant Silverlight projects: Buzzoggi (a web mashup), Robot Arena (a game), an association list box control, a product configurator for CinemaTech (home theater furniture), and a narrative storytelling device currently being tested at Silverlit Art.  In the process of building these I have built over a hundred test projects to explore the patterns used to develop Silverlight applications. &lt;br /&gt;&lt;br /&gt;This blog is about sharing what we have learned and sharing the journey.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6088992123466333517-6344891680508699842?l=silverlightfoundry.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://silverlightfoundry.blogspot.com/feeds/6344891680508699842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6088992123466333517&amp;postID=6344891680508699842&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/6344891680508699842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6088992123466333517/posts/default/6344891680508699842'/><link rel='alternate' type='text/html' href='http://silverlightfoundry.blogspot.com/2009/04/sharing-what-weve-learned-about.html' title='Sharing What We&apos;ve Learned about Silverlight'/><author><name>Silverlight Foundry</name><uri>http://www.blogger.com/profile/16423805971378858239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
