<?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'><id>tag:blogger.com,1999:blog-7601250593789026634</id><updated>2010-02-18T14:45:09.846-08:00</updated><title type='text'>Blog?</title><subtitle type='html'>WPF, Silverlight,Surface, Win7 touch, C# madness. A mash of all things technical.</subtitle><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default?start-index=26&amp;max-results=25'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.bradcunningham.net/rss.xml'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-6679863838703695878</id><published>2010-02-18T14:45:00.001-08:00</published><updated>2010-02-18T14:45:10.194-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CodePlex'/><category scheme='http://www.blogger.com/atom/ns#' term='Reactive Framework (Rx)'/><category scheme='http://www.blogger.com/atom/ns#' term='courier'/><title type='text'>Adding Rx Framework to Courier</title><content type='html'>&lt;p&gt;In a &lt;a href="http://www.bradcunningham.net/labels/courier.html"&gt;previous series of posts&lt;/a&gt; I introduced the &lt;a href="http://courier.codeplex.com/"&gt;Courier framework&lt;/a&gt;. Recently I have been doing some refactoring on the project and feature enhancements. The refactoring was fairly straight forward. &lt;/p&gt;  &lt;p&gt;I was never quite happy with the way that you unregistered for a message so I changed the model of message registration to return a token and then subsequently changed the signature of unregister to take in this token. That change was pretty straight forward and badly needed.&lt;/p&gt;  &lt;p&gt;The big feature in this update is the integration with the &lt;a href="http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx"&gt;Rx Framework&lt;/a&gt;. If you don’t understand Rx I suggest diving into &lt;a href="http://channel9.msdn.com/tags/Rx/"&gt;these videos&lt;/a&gt;. Be forewarned, the Rx guys are incredibly smart and tend to blaze through things very quickly. Much is left “up to the reader” to figure out and play with on their own. This makes it pretty difficult to &lt;a href="http://en.wikipedia.org/wiki/Grok"&gt;grok&lt;/a&gt;. I am not sure I really understand all the moving parts of Rx.&lt;/p&gt;  &lt;p&gt;One of my main goals in adding Rx to the &lt;a href="http://courier.codeplex.com/"&gt;Courier&lt;/a&gt; project was to allow you do include or exclude the Rx features with minimal pain. I also wanted to avoid a deep dependency on the Rx extension assembly. So I created a separate assembly for the Rx features that introduces an extension method to the Messenger class. This gives you an additional way to subscribe to a message and get an IObservable back. Since it is in a separate assembly you should be able to omit the assembly (and any dependency on Rx) pretty easily if you wanted to.&lt;/p&gt;  &lt;p&gt;So what does this change let you do? Essentially I have added one extension method to the messenger that gives you different method to subscribe for a message. Syntactically it looks like this &lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;IObservable myObservable = MyMessenger.RegisterForMessage(&amp;quot;Foo&amp;quot;);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This tells the messenger that you want to listen for the “Foo” message and get the result pushed into your myObservable sequence. So why is this cool? LINQ.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Plain and simple IObservable is queryable with LINQ and that makes for very interesting scenarios when you are dealing with a message pump that is very active and you want to filter out messages based on a criteria. I have added an example of how to use the new Rx extension method and tried to model the scenario into a real world situation. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Imagine you are listening to WCF service that is sending messages from a Blood Pressure monitor. Imagine the Messenger is broadcasting messages each time the Blood Pressure monitor sends some data.&amp;#160;&amp;#160; This can lead to a flood of messages firing through the Messenger. Using this new extension method you can write a simple LINQ query to filter these messages and only “react” to the ones you care about.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the scenario I show in the sample project I only care about messages when the blood pressure is outside of the “normal” range. In those cases I want to “react” and show some alert. I have written a quick and dirty simulation that will fire messages every second and randomize the pressure. When the pressure is outside of the predefined range I will get a message “pushed” into my IObservable sequence. When this happens I have a delegate that “reacts” to this “push” and does something (in my case I raise an alert)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So, from the snippet above I can take it one step further and do this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;IObservable&amp;lt;Object&amp;gt; observable = from msg in Mediator.RegisterForMessage(&amp;quot;BloodPressureMessage&amp;quot;)&lt;br /&gt;                                 where (((BloodPressure)msg).Systolic &amp;lt; 90 || ((BloodPressure)msg).Systolic &amp;gt; 119)&lt;br /&gt;                                 &amp;amp;&amp;amp; (((BloodPressure)msg).Diastolic &amp;lt; 60 || ((BloodPressure)msg).Diastolic &amp;gt; 79)&lt;br /&gt;                                 select msg;&lt;br /&gt;&lt;br /&gt;observable.Subscribe(OnAlertReceived);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice how I am now writing a LINQ query on the IObservable that the messenger is returning from the RegisterForMessage method. The line after the LINQ query is how I subscribe to the “push” events that happen on the observable sequence. OnAlertReceived is the delegate I want invoked when a new message is “pushed” on the IObservavle sequence.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Cool? I think so. Also, this check in I am going to promote to &lt;a href="http://courier.codeplex.com/releases/view/37264"&gt;Beta 2&lt;/a&gt; status. I have added unit tests and done some other small cleanup work. I think it is getting close to being ready for a true release. I would like to buff out the sample application a bit more and get some more API documentation in place and work out and remaining bugs. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;one little nit that I want to clean up in the next version is the casting of the “msg” in the LINQ Query. There are some internal issues with how I am implementing Rx under the covers that makes strong typing of the resulting observable challenging, I don’t have a solution for this yet given my current implementation, so if you find one please contribute it back to the project or let me know. &lt;/em&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-6679863838703695878?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/6679863838703695878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2010/02/adding-rx-framework-to-courier.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/6679863838703695878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/6679863838703695878'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2010/02/adding-rx-framework-to-courier.html' title='Adding Rx Framework to Courier'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-6191758093769992503</id><published>2010-02-18T08:44:00.001-08:00</published><updated>2010-02-18T08:44:55.887-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>Google Reader: Tip of the day – Mark as Unread</title><content type='html'>&lt;p&gt;I may well be the only one who didn’t know about this (and possibly the only one who cares about this) but I just found the holy grail for google reader. The &lt;a href="http://www.google.com/support/reader/bin/answer.py?hl=en&amp;amp;answer=69973"&gt;list of keyboard shortcuts&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I stumbled across this because I have been wanting a “mark as unread” option in reader like you have in Gmail. When I read through blogs I often will be interrupted in the middle of reading and need to go do something else. I haven’t determined if the blog is “star” worthy yet but I want to remind myself to go back and finish reading the blog entry. Hence the need for “mark as unread” in Google reader. &lt;/p&gt;  &lt;p&gt;It turns out this feature does exist but is hidden as a keyboard shortcut. Behold the letter “M”. With a blog entry highlighted simply press the letter M and ta-da! unread. Sweet.&amp;#160; &lt;/p&gt;  &lt;p&gt;There is a trove of other nice shortcuts in &lt;a href="http://www.google.com/support/reader/bin/answer.py?hl=en&amp;amp;answer=69973"&gt;the list&lt;/a&gt; as well. Like toggle full screen mode “U” and open the e-mail form “E”.&lt;/p&gt;  &lt;p&gt;Enjoy.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-6191758093769992503?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/6191758093769992503/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2010/02/google-reader-tip-of-day-mark-as-unread.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/6191758093769992503'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/6191758093769992503'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2010/02/google-reader-tip-of-day-mark-as-unread.html' title='Google Reader: Tip of the day – Mark as Unread'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-1742045557758248391</id><published>2010-01-11T21:47:00.001-08:00</published><updated>2010-01-12T10:36:58.225-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='op-ed'/><title type='text'>How to not suck at a technical interview*</title><content type='html'>&lt;p&gt;This is partially a rant and partially an honest to goodness attempt to raise the overall bar in our industry. Given that there are about 4 people who read this blog the latter is mostly a pipe dream but still.&lt;/p&gt;  &lt;p&gt;I have been involved in the interview process at my last couple companies. In the last few years I have picked up on a few things that I see consistently in interviewees. My hope is to distill these things in this post and try to offer some insight into what we, as interviewers, think of these traits and what we would really like to see from an interviewee.&lt;/p&gt;  &lt;p&gt;Ok enough altruism about helping the industry. Bottom line is &lt;strong&gt;MOST&lt;/strong&gt; applicants in the software development industry suck. Yeah yeah yeah, bitch all you want about my exaggerations and oversimplifications. The thing is, it’s true. Interviewing is painful. It is the exception not the rule that I find someone who is even worth more than 5 minutes of my time.&lt;/p&gt;  &lt;p&gt;For a while I honestly thought I was a bad interviewer and that my questions were too complicated or convoluted to be understood. I still don’t think I am the best interviewer by any means. I have however changed my approach to asking questions and try to work with the interviewee to get them talking and make them comfortable. But it isn’t my style that is broken it is the overall level of skill in the industry that is broken. &lt;/p&gt;  &lt;p&gt;I am not talking about&amp;#160; personality quirks, nervousness, or any other interview related issues. Look, I get it, programmers are a strange bunch. It is expected that you are going to interview odd balls, eccentrics, type A assholes whatever. I can deal with that. One piece of interviewing that I like to think I am ok at is filtering out these types of things and trying to identify the applicants true skill set. Sure, personality is part of an interview and certainly a vital part to team chemistry. I take a person’s personality traits very seriously in determining my opinion of the applicant. But, none of that matters if they don’t have the fundamental skill set needed.&lt;/p&gt;  &lt;p&gt;So here are a few things I see repeatedly during interviews.&lt;/p&gt;  &lt;p&gt;1. &lt;strong&gt;Stretching your skill set: &lt;/strong&gt;Ok, I get this one. I understand how it works, you need to throw the buzzwords on the resume to get your foot in the door. If you copy and paste a laundry list of the current buzzwords on your resume you better be prepared to answer questions about ANY of the buzzwords on your resume. Don’t tell me you are “an expert in Entity Framework and LinqToSQL” and not expect me to ask you a question about it. If you can’t hold your own in a discussion about a technology &lt;strong&gt;don’t put it on your resume&lt;/strong&gt;. Also, choose the nouns you use to clarify your skill level carefully. If you say you are an “expert” at something then I am going to drill you with deep technical questions. If you are an “expert” you better be able to teach a class on the technology. Don’t be afraid to say you are simply proficient or even that you are a novice. This sets my expectations properly so I can formulate questions. No one is an expert at everything, I don’t expect that. So when I see someone that is an “expert” at every current buzzword I get highly suspicious. &lt;/p&gt;  &lt;p&gt;2. &lt;strong&gt;Few details about current position: &lt;/strong&gt;I almost always lead with something like “tell me what you have been working on lately.” One, I am trying to ease the nerves and let the person talk about a subject they should be intimately familiar with. Inevitably I get some high level response with a bunch of superfluous buzz words and very little technical meat. This doesn’t help! If you can’t explain your current position, &lt;strong&gt;in detail&lt;/strong&gt;, I am already out on you. Out of any of the questions I am going to ask this is by far the simplest. Just tell me what you are working on. Talk to me like I am a co-worker and we are chatting in the hallway at work. I am a nerd too, I understand geek speak, I can fill in gaps. Don’t fear losing me or giving me to0 much detail. A solid response to this question frames the &lt;strong&gt;entire &lt;/strong&gt;rest of the interview. It gives me content to build on. It gives me areas to press you on. But, most importantly &lt;strong&gt;it give me insight into how you think&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;I really can’t stress that last sentence enough. It will be a recurring theme in this post.    &lt;br /&gt;    &lt;br /&gt;3. &lt;strong&gt;Unwillingness to say “I don’t know.” &lt;/strong&gt;Arggggghhh seriously, this one gives me a headache more than anything else. For god’s sake just say “You know, I am not sure I know the answer to that question.” So many people just try to talk themselves out of a corner or give some vague answer hoping I will buy it. Really? Do you really think,&amp;#160; if I ask you a question, that I don’t know the answer? If ask you something I damn well know the answer and I expect you to either give a correct answer or tell me you don’t know. BS’ing the answer or trying to weasel out of the question just pisses me off. Like I said, Arrrgggghhhh. Again, as I said, I have no expectation that people will be experts in everything. I am fine with you admitting you don’t know. Even if the question is related to something on your resume and you don’t know. I would &lt;strong&gt;much &lt;/strong&gt;rather you admit you don’t know then try to fake it. I will often ask questions that I fully expect the person not know the answer to. The reason for this is two fold. One, I want to see if you will admit your lack of understanding and two I want to see how you would go about finding the answer. In almost every programming job you are going to work on problems that you don’t know how to solve, what I want to know is how do you go about finding the answer. If you don’t know the answer to the question tell me you don’t know and add something about how you would go about finding the answer. Would you &lt;a href="http://www.google.com"&gt;Google&lt;/a&gt; it with &lt;a href="http://www.bing.com"&gt;Bing&lt;/a&gt;. Would you scour blogs, forums, pick a coworkers brain, fire up &lt;a href="http://www.red-gate.com/products/reflector/"&gt;reflector&lt;/a&gt;, read the &lt;a href="http://www.msdn.com"&gt;SDK&lt;/a&gt;. Whatever it is explain to me how you would go about it.&lt;/p&gt;  &lt;p&gt;4. &lt;strong&gt;Not enough use of the whiteboard. &lt;/strong&gt;This one sounds weird to most I think but it seriously makes a difference. In every single interview I have done the room we are interviewing in has a whiteboard. &lt;strong&gt;USE IT. &lt;/strong&gt;Not just use it but don’t be afraid to jump up and go for it. Every good programming problem requires a white board at some point. We use them daily in our jobs but for some reason we just don’t feel comfortable using them in an interview. I fully expect you to use a white board to solve hard problems in the day to day job so why not use it in the interview. More than anything, watching some one work through a problem on the whiteboard shows me how they think. Seriously, next time a co-worker jumps up to use a whiteboard pay attention to how they organize information on the board. How do they represent different conceptual aspects? How do they move through the flow of information? You can learn a lot things from how someone uses the whiteboard.&lt;/p&gt;  &lt;p&gt;5. &lt;strong&gt;Thinking too procedurally. &lt;/strong&gt;If you get nothing else from this rant please understand this. The number one issue I come across with applicants is a fundamental flaw in their problem solving approach. Too often people suffer from tunnel vision when it comes to solving problems. They find a solution to their problem and don’t take the time to understand why the particular solution works or what, conceptually, they have accomplished. I call this “thinking procedurally” because people seem to understand how to get from point A to point B but throw in even the smallest speed bump and they completely fall apart. They understand the “procedure” to get the work done but they fail to see the larger concept in play. This is the number one issue that causes me to end an interview or give a thumbs down on an applicant. This goes back to the previous two points. I don’t expect you to know everything, be willing to say I don’t know, but if the question sounds like something familiar work your way through the answer, &lt;strong&gt;out loud&lt;/strong&gt;. Talk me through your thinking. Explain to me where you are getting your background from and why you feel it might be similar to X. Use the whiteboard to draw it out (remember your high school math teacher “show your work!”). This is eye opening for me. Listening to you work through the problem and explaining how you would approach it shows me if you truly understand the concepts behind the solution or if you have tunnel vision and can’t see the forest for the trees.&lt;/p&gt;  &lt;p&gt;Ok I will wrap up my rant now. A few key takeaways if you made it this far. &lt;/p&gt;  &lt;p&gt;1. Expect questions about &lt;strong&gt;ANYTHING&lt;/strong&gt; on your resume. If you don’t know it, even if you did long ago but have since forgotten it, take it off your resume. &lt;/p&gt;  &lt;p&gt;2. Give me something to go on. Tell me about your recent work, &lt;strong&gt;in detail&lt;/strong&gt;. Tell me why you did things a certain way. Explain the challenges you faced. Explain what worked. Explain what didn’t.&lt;/p&gt;  &lt;p&gt;3. Recognize your shortcomings and &lt;strong&gt;be honest&lt;/strong&gt; about them. Explain how you would work to find the answer. Tell me what resources you use to solve these types of problems. What is your workflow? If it sounds sort of like something you are familiar with talk through it. Give me an insight into your thought process.&lt;/p&gt;  &lt;p&gt;4. Use all the tools you have at your disposal. Whiteboards are readily available during an interview. &lt;strong&gt;Use it&lt;/strong&gt;. Draw it out, organize your thoughts on the board. Don’t be afraid to scribble, erase, cross out or generally make a mess of the board (you should see mine right now)&lt;/p&gt;  &lt;p&gt;5. Think outside the box. Ok that cliché makes me vomit but in all seriousness &lt;strong&gt;understand the concepts&lt;/strong&gt;. If you don’t understand why your solution is actually working, spend time on it. Use &lt;a href="http://www.red-gate.com/products/reflector/"&gt;reflector&lt;/a&gt;, &lt;a href="http://msdn.microsoft.com/en-us/library/cc667410.aspx"&gt;step through the framework source&lt;/a&gt;, do whatever it takes for you to understand the fundamentals happening under the hood to solve your problem.&lt;/p&gt;  &lt;p&gt;Feel free to give me feedback on this. Am I being too harsh? Am I a dick? (I already know the answer to that one) Do you totally disagree? Praise, flame, bash whatever I am open to it.&lt;/p&gt;  &lt;p&gt;*&lt;strong&gt;NOTE&lt;/strong&gt;: This is a personal blog. The opinions expressed here represent my own and not those of my &lt;a href="http://www.InterKnowlogy.com"&gt;employer&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-1742045557758248391?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/1742045557758248391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2010/01/how-to-not-suck-at-technical-interview.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1742045557758248391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1742045557758248391'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2010/01/how-to-not-suck-at-technical-interview.html' title='How to not suck at a technical interview*'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-8579113334219131588</id><published>2010-01-01T18:57:00.001-08:00</published><updated>2010-01-07T17:18:35.173-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVP'/><title type='text'>Nice New Year’s surprise</title><content type='html'>&lt;p&gt;I got a very cool E-mail from Microsoft last week:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;“Congratulations! We are pleased to present you with the 2010 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Visual C# technical communities during the past year.”&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;w00t!&lt;/p&gt;  &lt;p&gt;I would have posted sooner about it but you wouldn’t believe the amount of NDA’s I had to sign just to be able to use the official MVP seal (see sidebar).&lt;/p&gt;  &lt;p&gt;I have updated my &lt;a href="https://mvp.support.microsoft.com/profile/Brad.Cunningham"&gt;MVP Profile&lt;/a&gt; and made it public for the masses.&lt;/p&gt;  &lt;p&gt;Who wants to touch me? :)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-8579113334219131588?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/8579113334219131588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2010/01/nice-new-years-surprise.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8579113334219131588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8579113334219131588'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2010/01/nice-new-years-surprise.html' title='Nice New Year’s surprise'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-3657047108263470385</id><published>2009-12-21T21:28:00.001-08:00</published><updated>2009-12-21T21:31:04.702-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVVM'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='CodePlex'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='courier'/><title type='text'>Decoupled ViewModel Messaging (Part 3)</title><content type='html'>&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code shown in this series has been published to &lt;/em&gt;&lt;a href="http://www.codeplex.com"&gt;&lt;em&gt;codeplex&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you would like to download the framework or the sample application that uses the framework you can find it here: &lt;/em&gt;&lt;a title="http://courier.codeplex.com/" href="http://courier.codeplex.com/"&gt;&lt;em&gt;http://courier.codeplex.com/&lt;/em&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; In this part of our saga we find or intrepid hero trapped in a ……. Wait where was I? So far in this series we have covered decoupled messaging between ViewModels at a &lt;a href="http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html"&gt;high level&lt;/a&gt; and we have looked at &lt;a href="http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-2.html"&gt;one specific enhancement&lt;/a&gt; that I have added to my courier framework that is lacking in other implementations. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; In this final post I am going to cover one more feature that I have added to the courier framework that I think provides a very nice addition to the overall process of decoupled ViewModel messaging and that is message caching. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; When I first started with this framework I really just set out to wrap my head around what others had done (&lt;a href="http://coremvvm.codeplex.com/"&gt;CoreMVVM&lt;/a&gt;,&lt;a href="http://cinch.codeplex.com/"&gt;Cinch&lt;/a&gt;, &lt;a href="http://www.codeplex.com/CompositeWPF"&gt;Prism&lt;/a&gt;, &lt;a href="http://mvvmfoundation.codeplex.com/"&gt;MVVM Foundation&lt;/a&gt;). Once I had gotten to that point I wanted to add a little something more to make the framework my own. What I found was that, in my scenarios, I found myself needing to cache messages for later retrieval.&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; The most obvious case for this is in the “Wizard” type scenario. When a user is performing a sequential set of actions I often have the need to pass data from one screen to the next. In this scenario the next screen is not created until after the previous screen is destroyed. This means that the message broadcast from screen one would happen before screen two is around to listen for it. With me so far? &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; So, to solve this problem I figured I would implement some sort of caching mechanism that would allow me to: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Broadcast a message from View one&lt;/li&gt;    &lt;li&gt;Save the message for re-broadcast &lt;/li&gt;    &lt;li&gt;Destroy View one&lt;/li&gt;    &lt;li&gt;Create View two&lt;/li&gt;    &lt;li&gt;Register for that message from View two&lt;/li&gt;    &lt;li&gt;Receive any, valid, cached copies of the message I registered for &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The first thing I did was to implement an internal List&amp;lt;T&amp;gt; inside the mediator class that would store these CachedMessage objects. When a message is broadcast with caching options I will save a copy of the message to this List&amp;lt;T&amp;gt;. Any subsequent registrations for this message will receive any valid cached copies of the messages. &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; So I added the following to the mediator &lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;private readonly List&amp;lt;CachedMessage&amp;gt; cachedMessages = new List&amp;lt;CachedMessage&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Where the CachedMessage class is defined like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;[DebuggerDisplay(&amp;quot;Message: {Message}, Parameter: {Parameter}&amp;quot;)]&lt;br /&gt;internal class CachedMessage&lt;br /&gt;{&lt;br /&gt;    public String Message { get; private set; }&lt;br /&gt;    public Object Parameter { get; private set; }&lt;br /&gt;    public CacheSettings CacheOptions { get; private set;}&lt;br /&gt;    public Int32 ResendCount { get; set; }&lt;br /&gt;&lt;br /&gt;    public CachedMessage(String message, Object parameter)&lt;br /&gt;    {&lt;br /&gt;        Message = message;&lt;br /&gt;        Parameter = parameter;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public CachedMessage(String message, Object parameter, CacheSettings cacheOptions)&lt;br /&gt;    {&lt;br /&gt;        CacheOptions = cacheOptions;&lt;br /&gt;        Message = message;&lt;br /&gt;        Parameter = parameter;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Two things to note here. First the CachedMessage class has a public property of type CacheSettings. This gives us the details of how long to keep the message for. Currently I am supporting two types of caching, time based and recurrence based. This means you can specify a specific DateTime when the message will expire or you can specify how many re-broadcasts before the message expires. The CacheSettings class looks like this: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;[DebuggerDisplay(&amp;quot;Expiration Date: {ExpirationDate}, NumberOfResends: {NumberOfResends}&amp;quot;)]&lt;br /&gt;public class CacheSettings&lt;br /&gt;{&lt;br /&gt;    public DateTime ExpirationDate { get; private set; }&lt;br /&gt;    public Int32 NumberOfResends { get; private set; }&lt;br /&gt;&lt;br /&gt;    public CacheSettings(DateTime expiration)&lt;br /&gt;    {&lt;br /&gt;        ExpirationDate = expiration;&lt;br /&gt;        NumberOfResends = Int32.MaxValue;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public CacheSettings(Int32 timesToResend)&lt;br /&gt;    {&lt;br /&gt;        NumberOfResends = timesToResend;&lt;br /&gt;        ExpirationDate = DateTime.MaxValue;&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; The second thing to note about both of these classes (CachedMessage and CacheSettings) is the use of the DebuggerDisplay attribute. I have just recently got in the habit of using this attribute religiously and I don’t know what I ever did without it. I won’t dive too in depth here about it, but suffice it to say, if you aren’t using it right now you should be. If you don’t know what it is stop reading here and jump over to my colleague, &lt;a href="http://team.interknowlogy.com/blogs/adamcalderon/default.aspx"&gt;Adam Calderon’s&lt;/a&gt;, excellent &lt;a href="http://team.interknowlogy.com/blogs/adamcalderon/archive/2008/11/02/writing-debugger-friendly-classes-using-the-debuggerdisplayattribute.aspx"&gt;post&lt;/a&gt; about it (don’t worry I will wait for you to come back). &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Ok, now that we are all writing Debugger friendly classes thanks to Adam, let’s wrap this post up with some usage scenarios. In the “Wizard” like case I talked about above I really just want to be able to broadcast a message and cache it for one re-broadcast. This allows me to broadcast the message from view one and then destroy view one and create view two. view two then registers for the message like it would normally and will immediately receive any messages that are in the cache. Once the message is dispatched from the cache we want to clean it out to prevent further re-broadcast. So first, two examples of how to call BroadcastMessage&amp;lt;T&amp;gt; with caching options &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;//NumberOfResend based caching example&lt;br /&gt;Mediator.BroadcastMessage(&amp;quot;Content1Message&amp;quot;,messageContent,new CacheSettings(1));&lt;br /&gt;&lt;br /&gt;//Time Based caching example&lt;br /&gt;Mediator.BroadcastMessage(&amp;quot;Content1Message&amp;quot;, messageContent, new CacheSettings(DateTime.Now.Add(TimeSpan.FromSeconds(30))));&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The first example show how to broadcast a message and specify that it should be cached for one re-broadcast. The second example shows how to broadcast a message and store it in the cache for 30 seconds after the first broadcast. Pretty straightforward so far. Now the two key methods in the Mediator class that handle keeping the cache clean and dispatching messages from cache: &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;private void GetMessagesFromCache(String message, Delegate callback)&lt;br /&gt;{&lt;br /&gt;    CleanOutCache();&lt;br /&gt;    //Search the cache for matches messages&lt;br /&gt;    List&amp;lt;CachedMessage&amp;gt; matches = cachedMessages.FindAll(action =&amp;gt; action.Message == message);&lt;br /&gt;    //If we find matches invoke the delegate passed in and pass the message payload&lt;br /&gt;    matches.ForEach(delegate(CachedMessage action)&lt;br /&gt;    {&lt;br /&gt;        callback.DynamicInvoke(action.Parameter);&lt;br /&gt;        action.ResendCount++;&lt;br /&gt;    });&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private void CleanOutCache()&lt;br /&gt;{&lt;br /&gt;    //Remove any expired messages from the cache&lt;br /&gt;    cachedMessages.RemoveAll(message =&amp;gt; (message.CacheOptions.ExpirationDate &amp;lt; DateTime.Now) || (message.ResendCount &amp;gt;= message.CacheOptions.NumberOfResends));&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; You can see in the GetMessagesFromCache method the first thing it does is clean out any expired messages from the cache. The CleanOutCache method uses the RemoveAll method on List&amp;lt;T&amp;gt; and an lambda to do a particularly elegant line of code. This code checks two properties of the CachedMessage objects (is it’s expiration date in the past OR has it been re-broadcast the max number of times?). If either is true it is removed from the CachedMessages list. A very succinct line of code for a normally cumbersome task. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; After the cache has been cleaned we call FindAll (again, using a simple lambda) to get all the messages from cache that match the one we are looking for (There could be multiple messages from different senders in the cache and we want to dispatch them all). Once we have the matching messages we invoke the callback that is registered and we increment the re-send count on the message. Overall, a pretty simple process, but it turns out to be very powerful. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; That wraps up this 3 part series ( &lt;a href="http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html"&gt;I&lt;/a&gt;, &lt;a href="http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-2.html"&gt;II&lt;/a&gt;, &lt;a href="http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-3.html"&gt;III&lt;/a&gt;) on the Courier framework. As I add new features to the framework I will post specific updates about the features. If anyone else is interested in joining the codeplex project and adding their ideas to the framework please feel free to contact me through this blog.&amp;#160;&amp;#160; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code shown in this series has been published to &lt;/em&gt;&lt;a href="http://www.codeplex.com"&gt;&lt;em&gt;codeplex&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you would like to download the framework or the sample application that uses the framework you can find it here: &lt;/em&gt;&lt;a title="http://courier.codeplex.com/" href="http://courier.codeplex.com/"&gt;&lt;em&gt;http://courier.codeplex.com/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-3657047108263470385?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/3657047108263470385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-3.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/3657047108263470385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/3657047108263470385'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-3.html' title='Decoupled ViewModel Messaging (Part 3)'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-7347412752163568573</id><published>2009-12-12T15:07:00.001-08:00</published><updated>2009-12-12T15:07:21.610-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVVM'/><category scheme='http://www.blogger.com/atom/ns#' term='CodePlex'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='courier'/><title type='text'>Decoupled ViewModel Messaging (Part 2)</title><content type='html'>&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code shown in this series has been published to &lt;/em&gt;&lt;a href="http://www.codeplex.com"&gt;&lt;em&gt;codeplex&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you would like to download the framework or the sample application that uses the framework you can find it here: &lt;/em&gt;&lt;a title="http://courier.codeplex.com/" href="http://courier.codeplex.com/"&gt;&lt;em&gt;http://courier.codeplex.com/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In my &lt;a href="http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html"&gt;previous post&lt;/a&gt; I discussed the ViewModel messaging framework at a high level and went over the basics of the implementation. Most of this is review if you are familiar with the other frameworks that I borrowed ideas from. &lt;/p&gt;  &lt;p&gt;In this post I want to touch on the two specific features I wanted to add to the other frameworks I had seen (hence the motivation behind this framework and this series of blog posts). Specifically, the two features I felt would be useful is the ability to explicitly unsubscribe from a particular message and the ability to cache messages for re-broadcast at a later date.&lt;/p&gt;  &lt;p&gt;The first feature seems obvious enough. There are times when you want to listen for messages and there are times that you want to stop listening for that message. Many of the frameworks mentioned &lt;a href="http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html"&gt;previously&lt;/a&gt; use WeakReferences to store the pointer to the message handler method. This works great when object are being destroyed. The Mediator object, which is responsible for delegating messages to their proper handlers, stores only a WeakReference to the handler and checks just prior to dispatching the message if the endpoint IsAlive. If it is then the message is dispatched. If it isn’t alive, then the endpoint is removed from the list of subscribers. This check looks something like this:&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;for (int i = weakSubscribers.Count - 1; i &amp;gt; -1; --i)&lt;br /&gt;{&lt;br /&gt;    WeakSubscriber weakSubscriber = weakSubscribers[i];&lt;br /&gt;    if (!weakSubscriber.IsAlive)&lt;br /&gt;        weakSubscribers.RemoveAt(i);&lt;br /&gt;    else&lt;br /&gt;        subscribers.Add(weakSubscriber.CreateAction());&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What this does is simple. It walks the collection of subscribers backwards and checks the IsAlive property. The IsAlive property on the WeakSubscriber class is simply looking at the underlying WeakReference.IsAlive property. If we find a dead subscriber we remove it from our list so that we don’t try to dispatch the message to an event handler method that has been destroyed.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This pattern works great is your subscriber objects, that is the object that has the event handler for the message in it, is being destroyed. However, I have situations where my object that contains the handler method for a message is still alive but I don’t want to receive any more messages of a given type from the mediator. In this case I need a way to tell the Mediator to remove from it’s list of subscribers. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To help with this I have added a method to the Messenger class call UnRegisterForMessage. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;//Method bodies elided for clarity &lt;br /&gt;public void UnRegisterForMessage(String message, Delegate callback)&lt;br /&gt;{&lt;br /&gt;    ...&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This method takes in the message you want to unsubscribe to and the handler you want to remove for that message. For a given message and object can have multiple handlers. This method allows you to unsubscribe a particular handler while, potentially keeping the other handlers subscribed.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;On caveat to this approach is how I am passing the reference to the handler method. In the internal unregister process&amp;#160; I need a way to determine which handler I am removing from which message. The only way I could find to make this work was to pass a reference to the delegate itself. The remove method inside the MessageToSubscriberMap class looks like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;internal void RemoveSubscriber(String message, Delegate callback)&lt;br /&gt;{&lt;br /&gt;    lock (map)&lt;br /&gt;    {&lt;br /&gt;        if (map.ContainsKey(message))&lt;br /&gt;        {&lt;br /&gt;            map[message].RemoveAll(subscriber =&amp;gt; subscriber.Method == callback.Method);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This works fine but the usage is a bit strange and has one glaring issue that I have yet to find a solution for. Let me demonstrate. I if I want to unsubscribe from a message called “UserChanged.” I would write something like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;Mediator.UnRegisterForMessage(&amp;quot;UserChanged&amp;quot;, (Action&amp;lt;IUser&amp;gt;)OnUserChanged)&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice the second parameter here. I am the reference to the delegate OnUserChanged and casting it as an action. This will work just fine. However, in some internal projects I have used this framework and noticed other developers do something like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;Mediator.UnRegisterForMessage(&amp;quot;UserChnaged&amp;quot;, new Action&amp;lt;IUser&amp;gt;(OnUserChnaged))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Notice the difference? Subtle maybe, but it is critical to understand the problem here. In the second example the second parameter, instead of being cast as an Action&amp;lt;T&amp;gt; a new instance of an Action&amp;lt;T&amp;gt; is being created and passed in. This will not point to the same instance of the delegate passed in on the Register call. This means the unsubscribe will not find a match and will not remove the handler. This means you will continue to get messages broadcast. In general, I am not completely satisfied with the unsubscribe method signature and may change it in the future.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;#160; This post is getting a bit long winded so I will stop here and in my next post I will describe message caching and how I went about implementing it.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code shown in this series has been published to &lt;/em&gt;&lt;a href="http://www.codeplex.com"&gt;&lt;em&gt;codeplex&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you would like to download the framework or the sample application that uses the framework you can find it here: &lt;/em&gt;&lt;a title="http://courier.codeplex.com/" href="http://courier.codeplex.com/"&gt;&lt;em&gt;http://courier.codeplex.com/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-7347412752163568573?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/7347412752163568573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7347412752163568573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7347412752163568573'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/12/decoupled-viewmodel-messaging-part-2.html' title='Decoupled ViewModel Messaging (Part 2)'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-2944677018385720114</id><published>2009-11-17T17:51:00.001-08:00</published><updated>2009-12-21T21:32:16.625-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MVVM'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='CodePlex'/><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='courier'/><title type='text'>Decoupled ViewModel Messaging (Part 1)</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code shown in this series has been published to &lt;/em&gt;&lt;a href="http://www.codeplex.com"&gt;&lt;em&gt;codeplex&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you would like to download the framework or the sample application that uses the framework you can find it here: &lt;/em&gt;&lt;a title="http://courier.codeplex.com/" href="http://courier.codeplex.com/"&gt;&lt;em&gt;http://courier.codeplex.com/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Lately I have been playing around with different ways to decouple the communication between ViewModels in the MVVM pattern. My focus has been in WPF, as this is what the MVVM pattern is suited for however, this messaging technique is not specific to WPF and could be used in any other decoupled solution (MVC, MVP etc..)&lt;/p&gt;  &lt;p&gt;I poked around on the tubes looking for examples of how other people have solved this problem and there are many different options out there. My implementation borrows heavily from the &lt;a href="http://coremvvm.codeplex.com/"&gt;CoreMVVM&lt;/a&gt; framework on codeplex which itself borrows bits from &lt;a href="http://cinch.codeplex.com/"&gt;Cinch&lt;/a&gt;, &lt;a href="http://www.codeplex.com/CompositeWPF"&gt;Prism&lt;/a&gt;, &lt;a href="http://mvvmfoundation.codeplex.com/"&gt;MVVM Foundation&lt;/a&gt; etc..&amp;#160; &lt;/p&gt;  &lt;p&gt;My first goal was to really just get down in the weeds and understand how these other frameworks were handling decoupled messaging between objects. Once I wrapped my head around it I then came up with two features that I thought would be nice to have in a messaging solution that I hadn’t seen in other frameworks. &lt;/p&gt;  &lt;p&gt;The ability to manually unsubscribe from messages and the ability cache messages for re-broadcast.&lt;/p&gt;  &lt;p&gt;Before I dive in and talk about the new features I wanted to add let me go over the basic implementation of the Mediator pattern I did. Again, this is very similar to how the &lt;a href="http://coremvvm.codeplex.com/"&gt;CoreMVVM&lt;/a&gt; framework does it, so if you are familiar with that framework this should review.&lt;/p&gt;  &lt;p&gt;The basis of the implementation is a basic mediator pattern. You have a mediator object that stores a mapping of subscribers and messages. This gives the mediator enough information to understand what messages to dispatch to what subscribers. The mediator in my case looks like this&amp;#160; &lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;//Method bodies elided for clarity&lt;br /&gt;public class Mediator&lt;br /&gt;{&lt;br /&gt;    private readonly MessageToSubscriberMap subscribers = new MessageToSubscriberMap();&lt;br /&gt;    private readonly List&amp;lt;CachedMessage&amp;gt; cachedMessages = new List&amp;lt;CachedMessage&amp;gt;();&lt;br /&gt;&lt;br /&gt;    public void RegisterForMessage(String message, Delegate callback)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void UnRegisterForMessage(String message, Delegate callback)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void BroadcastMessage&amp;lt;T&amp;gt;(String message, Boolean cacheMessage, T parameter)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void BrodcastMessage&amp;lt;T&amp;gt;(String message, Boolean cacheMessage)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void GetMessagesFromCache(String message, Delegate callback)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;From the snippet above you can see there isn’t much going on in the Mediator. The key is really the MessageToSubscriberMap object defined at the top. This object is what stores the (weak) reference to the subscriber (in this case a delegate to be invoked) and the message that subscriber is interested in.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here are the guts of the MessageToSubscriberMap class&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;//Method bodies elided for clarity&lt;br /&gt;internal class MessageToSubscriberMap&lt;br /&gt;{&lt;br /&gt;    //Store mappings with weak references to prevent leaks&lt;br /&gt;    private readonly Dictionary&amp;lt;String, List&amp;lt;WeakSubscriber&amp;gt;&amp;gt; map = new Dictionary&amp;lt;String, List&amp;lt;WeakSubscriber&amp;gt;&amp;gt;();&lt;br /&gt;    internal void AddSubscriber(String message, Object target, MethodInfo method, Type subscriberType)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    internal void RemoveSubscriber(String message, Delegate callback)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    internal List&amp;lt;Delegate&amp;gt; GetSubscribers(String message)&lt;br /&gt;    {&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The key piece of this map is the private Dictionary field. This is the mapping of Messages to the collection of WeakSubscribers that are listening for that message. I have called the object WeakSubscriber to indicate that a subscriber is really a WeakReference to a delegate. Here is the complete implementation of the WeakSubscriber class&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;internal class WeakSubscriber&lt;br /&gt;{&lt;br /&gt;    private readonly MethodInfo method;&lt;br /&gt;&lt;br /&gt;    public MethodInfo Method { get { return method; } } &lt;br /&gt;&lt;br /&gt;    private readonly Type delegateType;&lt;br /&gt;    private readonly WeakReference weakReference;&lt;br /&gt;&lt;br /&gt;    internal WeakSubscriber(Object target, MethodInfo method, Type parameterType)&lt;br /&gt;    {&lt;br /&gt;        //create a WeakReference to store the instance of the target in which the Method resides&lt;br /&gt;        weakReference = new WeakReference(target);&lt;br /&gt;        this.method = method;&lt;br /&gt;        delegateType = parameterType == null ? typeof(Action) : typeof(Action&amp;lt;&amp;gt;).MakeGenericType(parameterType);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    internal Delegate CreateAction()&lt;br /&gt;    {&lt;br /&gt;        Object target = weakReference.Target;&lt;br /&gt;        return target != null ? Delegate.CreateDelegate(delegateType,weakReference.Target,method) : null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Boolean IsAlive&lt;br /&gt;    {&lt;br /&gt;        get { return weakReference.IsAlive; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ok so now we have seen the extent of my little messaging framework. Again, most of this code is very similar to the &lt;a href="http://coremvvm.codeplex.com/"&gt;CoreMVVM&lt;/a&gt; framework implementation of the mediator pattern so, for users of that framework, this should be familiar.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I am going to wrap this post up with a quick example of how you would subscribe to a message and how you would broadcast a message with this framework.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To broadcast a message you would do this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;Mediator.BroadcastMessage(&amp;quot;Content1Message&amp;quot;,true, messageContent);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Note the second parameter in this method call is for caching the message which I will explain in a following post. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you wanted to subscribe to this Content1Message you would register for the message like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;Mediator.RegisterForMessage(&amp;quot;Content1Message&amp;quot;, (Action&amp;lt;String&amp;gt;)OnContent1MessageReceived);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In the next post I am going to describe the two new features I added to the framework which are the ability to unsubscribe from a message and the ability to cache messages for re-broadcast. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;This project was built in Visual Studio 2010 Beta 2, If you haven’t already I highly recommend downloading &lt;a href="http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx"&gt;VS2010&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;As a side note, the specific reason I using VS2010 is because I plan on parallelizing the dispatching of messages to subscribers in the future and want to use the new &lt;a href="http://msdn.microsoft.com/en-us/concurrency/default.aspx"&gt;parallel framework in .NET 4.0&lt;/a&gt;&amp;#160; &lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; All the code shown in this series has been published to &lt;/em&gt;&lt;a href="http://www.codeplex.com"&gt;&lt;em&gt;codeplex&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. If you would like to download the framework or the sample application that uses the framework you can find it here: &lt;/em&gt;&lt;a title="http://courier.codeplex.com/" href="http://courier.codeplex.com/"&gt;&lt;em&gt;http://courier.codeplex.com/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-2944677018385720114?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/2944677018385720114/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2944677018385720114'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2944677018385720114'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html' title='Decoupled ViewModel Messaging (Part 1)'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-6131297963507052715</id><published>2009-10-22T11:45:00.000-07:00</published><updated>2009-10-22T11:45:00.300-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nerd Debate'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Random Nerd Debates : Episode 2 VAR</title><content type='html'>&lt;p&gt;In the second episode of Random Nerd debates we are doing to discuss the use of the C# keyword var.&lt;/p&gt;  &lt;p&gt;First, what is var? &lt;a href="http://msdn.microsoft.com/en-us/library/bb383973.aspx"&gt;MSDN&lt;/a&gt; has a very succinct explanation of the keyword:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;“Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type.” &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;And the simple code example: &lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;var i = 10; // implicitly typed&lt;br /&gt;int i = 10; //explicitly typed&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ok so now that we are both on the same page let’s talk about usage of this keyword. I have a very specific rule when it comes to the usage of var. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I will only use the var keyword to shorten my code without obscuring the clarity. This means I will only use the var keyword if the type can be inferred directly by viewing the right side of the operation. By “directly” I mean that the type is explicitly specified in the right side of the operation. I don’t want to have to jump to the method declaration or hover over the expression to determine the type. The best way to show this is through code examples:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;//Since foo is clearly specified on the right side I WILL use var in this case&lt;br /&gt;var foo = new Foo();&lt;br /&gt;&lt;br /&gt;//Since the return type of the method GetBar() is not clear I WILL NOT use var in this case&lt;br /&gt;var bar = GetBar();&lt;br /&gt;&lt;br /&gt;//Other places where I WILL use var&lt;br /&gt;var foo = (Foo)bar;&lt;br /&gt;var bar = foo as Bar;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The benefit of the var keyword is allowing to write more succinct code. To me, succinctness can not come at the cost of clarity. In my examples above where I WILL use var I don’t feel like I am sacrificing any clarity but I am reducing noise.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There are two exceptions to my rule. When writing a LINQ query you almost always see the use of var and so I will follow that convention&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;var files = from file in enumerableFiles&lt;br /&gt;            select new Uri(file.FullName,UriKind.Absolute);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The other exception is similar to the LINQ example but more specific. There are cases which I want to deliberately de-emphasize the underlying storage mechanism and keep it ambiguous. In these cases I will use var to purposely obscure the underlying type. &lt;a href="http://blogs.msdn.com/ericlippert/default.aspx"&gt;Eric Lippert&lt;/a&gt; explained this idea well in a &lt;a href="http://blogs.msdn.com/ericlippert/archive/2009/02/06/santalic-tailfans-part-two.aspx"&gt;blog post&lt;/a&gt;. The tidbit from Lippert was this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160; “Another subtle point here: notice how when I changed the type of the variable &amp;quot;racks&amp;quot; from &amp;quot;array of string&amp;quot; to &amp;quot;set of string&amp;quot;, I didn't have to redundantly change the type thanks to implicit typing of local variables. I want to emphasize the semantics here, not the storage mechanism. If I felt that communicating the storage mechanism was an important part of this code -- because it has such a strong effect on performance -- perhaps I would choose to emphasize the storage by eschewing the &amp;quot;&lt;b&gt;var&lt;/b&gt;&amp;quot;.&amp;quot;&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;If you don’t already follow Eric’s blog I highly recommend it.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So I pose the question to you? Do you use var? Do you have a specific rule you follow when it comes to using it? Did you read this whole post and realize you just wasted the last 20 minutes of your life?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-6131297963507052715?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/6131297963507052715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/10/random-nerd-debates-episode-2-var.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/6131297963507052715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/6131297963507052715'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/10/random-nerd-debates-episode-2-var.html' title='Random Nerd Debates : Episode 2 VAR'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-5772125025135378347</id><published>2009-10-16T09:56:00.001-07:00</published><updated>2009-10-16T10:01:55.250-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>Seeing Stars I’m Seeing Stars</title><content type='html'>&lt;p&gt;“Oh my, starry eyed surprise. Sun down to sun rise. Dance all night. We gonna dance all night…”&lt;/p&gt;  &lt;p&gt;Feel free to stab your eyes out at this point (Or drink a &lt;a href="http://www.youtube.com/watch?v=ZmBDeswu2dI"&gt;Diet Coke&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;Ok so WTF am I talking about? Custom Ink Canvas rendering in WPF of course… I ran across a problem recently that I thought was blog worthy. The objective was to allow a user to draw on an InkCanvas with a custom “stencil.” The “stencil” is really just some custom shape that should be used as the stroke for the InkCanvas. This is kind of hard to explain so a picture may help&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_MRQ9Z0kgSJI/Stilo_QPg9I/AAAAAAAABHc/tjqvTMLcs-k/s1600-h/SurfaceCustomInking12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SurfaceCustomInking[1]" border="0" alt="SurfaceCustomInking[1]" src="http://lh4.ggpht.com/_MRQ9Z0kgSJI/Stilpr_h6WI/AAAAAAAABHg/lq4Xvm9mW1s/SurfaceCustomInking1_thumb.png?imgmax=800" width="184" height="107" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In this picture the stars (hence the terrible &lt;a href="http://www.pauloakenfold.com/"&gt;Oakenfold&lt;/a&gt; reference) would be the stencil. When the user drags the mouse around the canvas we want to draw the stars like shown above. This isn’t quite as obvious to implement as most things in WPF. My hope was that I could just set the Stroke to some DrawingBrush and be done. However, it isn’t that easy.&lt;/p&gt;  &lt;p&gt;The main reason for the complication is the way that the InkCanvas collects the strokes from the user. The strokes are are collected on a background thread to ensure that all strokes will be collected, even if the UI is blocking. This is done through a DynamicRenderer object. This object collects the user input and renders all points in the stroke on a separate thread.&amp;#160; Once the entire stroke is collected The InkCanvas raises the OnStrokeCollected method. &lt;/p&gt;  &lt;p&gt;The first step to solving my problem is to implement a custom DynamicRenderer&amp;#160; that will track the users movements on the canvas and render our custom shape along the path that the user has drawn.&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public class CustomRenderer : DynamicRenderer&lt;br /&gt;{&lt;br /&gt;    private Point prevPoint;&lt;br /&gt;&lt;br /&gt;    public DrawingGroup Stencil { get; set; }&lt;br /&gt;&lt;br /&gt;    protected override void OnStylusDown(RawStylusInput rawStylusInput)&lt;br /&gt;    {&lt;br /&gt;        // Allocate memory to store the previous point to draw from.&lt;br /&gt;        prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);&lt;br /&gt;        base.OnStylusDown(rawStylusInput);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected override void OnDraw(DrawingContext drawingContext,StylusPointCollection stylusPoints,Geometry geometry, Brush fillBrush)&lt;br /&gt;    {&lt;br /&gt;        for (int i = 0; i &amp;lt; stylusPoints.Count; i++)&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            var pt = (Point)stylusPoints[i];&lt;br /&gt;            Vector v = Point.Subtract(prevPoint, pt);&lt;br /&gt;            &lt;br /&gt;            // Only draw if we are at least 4 units away &lt;br /&gt;            // from the end of the last ellipse. Otherwise, &lt;br /&gt;            // we're just redrawing and wasting cycles.&lt;br /&gt;            if (v.Length &amp;gt; 4)&lt;br /&gt;            {&lt;br /&gt;                var clone = Stencil.Clone();&lt;br /&gt;                clone.Transform = new TranslateTransform(pt.X, pt.Y);&lt;br /&gt;                drawingContext.DrawDrawing(clone);&lt;br /&gt;                prevPoint = pt;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The key to this snippet is in the OnDraw method override. I am iterating through the points along the path that the user has drawn then rendering a new instance of our custom drawing to the DrawingContext pipeline. Notice the TranslateTransform, I am using the translate to make sure the drawing I add to the DrawingContext pipeline follows the points in the path that the user created.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Once the stylus points are converted to strokes then the stroke is told to render itself. This is the second step in the process. We need to create a custom stroke class that renders our custom shape when it is asked to render itself.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;class CustomStroke : Stroke&lt;br /&gt;{&lt;br /&gt;    public DrawingGroup Stencil { get; set; }&lt;br /&gt;&lt;br /&gt;    public CustomStroke(StylusPointCollection stylusPoints) : base(stylusPoints)&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected override void DrawCore(DrawingContext drawingContext,DrawingAttributes drawingAttributes)&lt;br /&gt;    {&lt;br /&gt;        // Allocate memory to store the previous point to draw from.&lt;br /&gt;        var prevPoint = new Point(double.NegativeInfinity,&lt;br /&gt;                                  double.NegativeInfinity);&lt;br /&gt;&lt;br /&gt;        // Draw linear gradient ellipses between &lt;br /&gt;        // all the StylusPoints in the Stroke.&lt;br /&gt;        for (int i = 0; i &amp;lt; StylusPoints.Count; i++)&lt;br /&gt;        {&lt;br /&gt;            var pt = (Point)StylusPoints[i];&lt;br /&gt;            Vector v = Point.Subtract(prevPoint, pt);&lt;br /&gt;&lt;br /&gt;            // Only draw if we are at least 4 units away &lt;br /&gt;            // from the end of the last ellipse. Otherwise, &lt;br /&gt;            // we're just redrawing and wasting cycles.&lt;br /&gt;            if (v.Length &amp;gt; 4)&lt;br /&gt;            {&lt;br /&gt;                var clone = Stencil.Clone();&lt;br /&gt;                clone.Transform = new TranslateTransform(pt.X, pt.Y);&lt;br /&gt;                drawingContext.DrawDrawing(clone);&lt;br /&gt;                prevPoint = pt;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can see the DrawCore method looks very similar to the OnDraw method in the custom renderer. We are doing the same rendering in both places so the code will be very similar.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The final step in this process is to create a class that inherits from InkCanvas and wire up the dynamic renderer and the custom stroke.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;public class CustomRenderingInkCanvas : InkCanvas&lt;br /&gt;{&lt;br /&gt;    readonly CustomRenderer customRenderer = new CustomRenderer();&lt;br /&gt;&lt;br /&gt;    public CustomRenderingInkCanvas(): base()&lt;br /&gt;    {&lt;br /&gt;        // Use the custom dynamic renderer on the&lt;br /&gt;        // custom InkCanvas.&lt;br /&gt;        DynamicRenderer = customRenderer;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)&lt;br /&gt;    {&lt;br /&gt;        // Remove the original stroke and add a custom stroke.&lt;br /&gt;        Strokes.Remove(e.Stroke);&lt;br /&gt;        var customStroke = new CustomStroke(e.Stroke.StylusPoints)&lt;br /&gt;                               {&lt;br /&gt;                                   Stencil = Stencil&lt;br /&gt;                               };&lt;br /&gt;&lt;br /&gt;        Strokes.Add(customStroke);&lt;br /&gt;&lt;br /&gt;        // Pass the custom stroke to base class' OnStrokeCollected method.&lt;br /&gt;        var args = new InkCanvasStrokeCollectedEventArgs(customStroke);&lt;br /&gt;        base.OnStrokeCollected(args);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I have cut out some code from the snippet above to focus on the important parts. The two keys are wiring up the DynamicRenderer in the public constructor and removing the default stroke and adding in our custom stroke in the StrokeCollected override&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Once we put all these steps together we end up with an ink canvas that we can apply a custom stencil to and use that stencil to draw with.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The result is shown in the video below ( Turn on your sound ;)&lt;/p&gt;&lt;br /&gt;&lt;object width="400" height="240"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=7100955&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=7100955&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="240"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://vimeo.com/7100955"&gt;Custom InkCanvas in WPF&lt;/a&gt; from &lt;a href="http://vimeo.com/bradcunningham"&gt;Brad Cunningham&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;em&gt;&lt;font size="1"&gt;&lt;strong&gt;Note&lt;/strong&gt;: the lag you see in the video is just from me trying to draw using the trackpad on my laptop with one hand. The actual application doesn’t lag. &lt;/font&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can download the full sample project from &lt;a href="http://www.BradCunningham.net/SourceCode/CustomInkCanvas/CustomInkCanvas.zip"&gt;here&lt;/a&gt;. I followed this &lt;a href="http://msdn.microsoft.com/en-us/library/ms747347%28VS.85%29.aspx"&gt;MSDN article&lt;/a&gt; in solving this problem&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-5772125025135378347?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/5772125025135378347/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/10/seeing-stars-im-seeing-stars.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/5772125025135378347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/5772125025135378347'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/10/seeing-stars-im-seeing-stars.html' title='Seeing Stars I’m Seeing Stars'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-7580261679705835765</id><published>2009-09-09T11:25:00.001-07:00</published><updated>2009-09-09T15:20:02.572-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Nerd Debate'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Random nerd debates</title><content type='html'>&lt;p&gt;Working as an engineer means that you get involved in random nerd debates on (at least) a weekly basis. &lt;/p&gt;  &lt;p&gt;Most of these debates are useless drivel that aren’t worth noting but occasionally a topic comes up that is worth some level of posterity. Since my blog is otherwise full of useless stuff I figure starting a series on nerd debates isn’t the worst thing I could do :)&amp;#160; &lt;/p&gt;  &lt;p&gt;So episode 1 of the Random nerd debate series. &lt;/p&gt;  &lt;p&gt;&lt;font size="1"&gt;(&lt;em&gt;Interestingly you will notice that SyntaxHighlighter doesn’t even understand the Class name syntax Boolean, but does understand the alias syntax)&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;bool&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Vs.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;Boolean&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Or int Vs. Int32 or whatever you want to call it. I am pretty sure I am in the minority here but I tend to prefer using the class name syntax Boolean Vs. the alias syntax bool. It is mostly personal preference but I think there are two key areas where the distinction makes a difference. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;First when you are calling static methods that live on the class it seems weird to me to use the alias syntax. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;bool.TryParse()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;doesn’t feel the same as &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;Boolean.TryParse()&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Again, I think I am in the minority here. My thought is that when you are calling methods you are doing so on the class itself. Using the alias just adds a level of indirection, albeit a minor and mostly overlooked one. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The second place where I think class name syntax gives you a true benefit is in clarity. When using the alias syntax int I have heard several people think that Int32 is simply a implementation detail and that the alias int hides that from you. So if you were compiling on x64 int would translate into Int64 instead of Int32. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is a misconception however the int alias is simply that, an alias, or syntactic sugar for Int32. If you want Int64 you have to use the alias long. Of course you could specify Int64 explicitly using class name syntax and be done with it. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The more 64 bit programming becomes the norm I think the more we will run into some confusion. Do you use int, or double, or float, or long etc… &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Interestingly the alias double maps to the class Double but the alias float maps to the class Single (have you ever seen someone use Single in their code?) In a chat with a &lt;a href="http://www.claassen.net/geek/blog/" target="_blank"&gt;friend&lt;/a&gt; about this topic his response was &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;em&gt;“I go with shorter just from habit, but would generally defer to the team standard. i.e. it's not an issue I feel strongly about, but do feel that a decision one way or another needs to be made on a project”&lt;/em&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Generally I agree with that statement and I think team level consistency is important. I think in most cases you will see teams using the alias and I think, in most case, this works out fine for them. All programmers can read the alias and I think that some may even be confused at first if they see the ClassName syntax and haven’t seen it before but, to me, it increases clarity and intent. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://stackoverflow.com/" target="_blank"&gt;Stack Overflow&lt;/a&gt; had a nice &lt;a href="http://stackoverflow.com/questions/134746/what-is-the-difference-between-bool-and-boolean-types-in-c" target="_blank"&gt;thread&lt;/a&gt; about this very thing that I found while poking around for this post &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can find a complete list of all the built in type aliases for .NET, and their equivalent class name &lt;a href="http://msdn.microsoft.com/en-us/library/ya5y69ds.aspx" target="_blank"&gt;here&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In a bit of a contradiction of style I do however use the var keyword very often. Which may sound like it reduces code clarity but there are places in which I purposely want to abstract the implementation details of the backing type from my code. But that debate is for episode 2. Stay tuned.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-7580261679705835765?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/7580261679705835765/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/09/random-nerd-debates.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7580261679705835765'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7580261679705835765'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/09/random-nerd-debates.html' title='Random nerd debates'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-8058350007745800715</id><published>2009-09-06T11:55:00.001-07:00</published><updated>2009-09-06T11:55:21.056-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WPF'/><category scheme='http://www.blogger.com/atom/ns#' term='XAML'/><title type='text'>Grouping and Checkboxes in WPF</title><content type='html'>&lt;p&gt;If you have done any with WPF radio buttons you know that WPF has given us greater flexibility to define radio groups. In WinForms radio button groups were constrained to the parent panel. This meant if you wanted radio buttons to be mutually exclusive, that is you can only have one selected at a time, they all had to live within the same parent layout panel. &lt;/p&gt;  &lt;p&gt;In WPF you don’t have this limitation, when you specify a group name for a radio button it will be mutually exclusive to any other radio button that has the same group name within the visual tree. This gives you greater flexibility with how you layout your radio groups.&lt;/p&gt;  &lt;p&gt;Recently, I had the need to show a popup menu within a complex layout scenario and I needed there to be only one popup open at a time. So I originally went down the route of using radio buttons. I figured I could layout radio buttons anywhere in the visual tree, give them all the same group name and then bind the IsOpen property of popup to the IsChecked property of my radio button.&lt;/p&gt;  &lt;p&gt;This worked fine at first, however I quickly found out that once a popup was open, i.e. one of the radio buttons in the group was checked, from that point on you always had one popup open. The problem is you can’t “un-select” a radio button once it has been checked. This was not the desired behavior for my situation so I set out to find a solution that would give me mutual exclusivity and the ability to have an unchecked state for my entire group, that is nothing in the group is selected.&lt;/p&gt;  &lt;p&gt;Enter the grouping checkboxes. What I wanted was the check / uncheck behavior of checkbox (really of the base toggle&amp;#160; button) with the functionality of a radio button. So I decided to do this through a simple attached property. &lt;/p&gt;  &lt;p&gt;First I created a class called ToggleButtonExtensions. I decided to pull the functionality up to the base ToggleButton class since there is nothing in the checkbox class that I need and I wanted to give the flexibility.&amp;#160; This is where I am going to define my custom attached property and handle the changed event when the ToggleButton checked event fires. &lt;/p&gt;  &lt;p&gt;So first I define my custom attached property called GroupName (I wanted the usage to feel as much like the radio button grouping as possible)&lt;/p&gt;  &lt;pre class="brush: csharp;"&gt;public static readonly DependencyProperty GroupNameProperty = DependencyProperty.RegisterAttached(&amp;quot;GroupName&amp;quot;,typeof(String),typeof(ToggleButtonExtensions),new PropertyMetadata(String.Empty, OnGroupNameChanged));&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The key to hooking into the ToggleButton checked event is in the property change handler on this custom attached property. At the end of the code snippet above you see the method name OnGroupNameChanged. In that method we can get a hold of the element that is using this attached property and hook into it’s events. The body of that method looks like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;private static void OnGroupNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&lt;br /&gt;{&lt;br /&gt;    //Add an entry to the group name collection&lt;br /&gt;    var toggleButton = d as ToggleButton;&lt;br /&gt;    if (toggleButton != null)&lt;br /&gt;    {&lt;br /&gt;        String newGroupName = e.NewValue.ToString();&lt;br /&gt;        String oldGroupName = e.OldValue.ToString();&lt;br /&gt;        if (String.IsNullOrEmpty(newGroupName))&lt;br /&gt;        {&lt;br /&gt;            //Removing the toggle button from grouping&lt;br /&gt;            RemoveCheckboxFromGrouping(toggleButton);&lt;br /&gt;        }&lt;br /&gt;        else&lt;br /&gt;        {&lt;br /&gt;            //Switching to a new group&lt;br /&gt;            if (newGroupName != oldGroupName)&lt;br /&gt;            {&lt;br /&gt;                if (!String.IsNullOrEmpty(oldGroupName))&lt;br /&gt;                {&lt;br /&gt;                    //Remove the old group mapping&lt;br /&gt;                    RemoveCheckboxFromGrouping(toggleButton);&lt;br /&gt;                }&lt;br /&gt;                ElementToGroupNames.Add(toggleButton, e.NewValue.ToString());&lt;br /&gt;                toggleButton.Checked += ToggleButtonChecked;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There are a few things going on here, first you see the last line in the method is hooking into the Checked event of the ToggleButton. This gives us a way to go through the other ToggleButtons that are a part of this group and “un-check” them. This will give us the mutual exclusivity we want.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The other thing in the method to note is how I am managing the groups of ToggleButtons. I have a simple dictionary that stores a GroupName to ToggleButton mapping. This gives me a handle to the ToggleButtons so I can uncheck them if another element in the same group gets checked.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The last thing we need to do is implement the Checked handler where we can iterate over the dictionary and uncheck any other elements in the same group as the element that is being checked. That handler method looks like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;static void ToggleButtonChecked(object sender, RoutedEventArgs e)&lt;br /&gt;{&lt;br /&gt;    var toggleButton = e.OriginalSource as ToggleButton;&lt;br /&gt;    foreach(var item in ElementToGroupNames)&lt;br /&gt;    {&lt;br /&gt;        if (item.Key != toggleButton &amp;amp;&amp;amp; item.Value == GetGroupName(toggleButton))&lt;br /&gt;        {&lt;br /&gt;            item.Key.IsChecked = false;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;And that’s it. Now we have mutually exclusive toggle buttons that allow us to have an unchecked state for the whole group.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can check out the sample project &lt;a href="http://BradCunningham.net/SourceCode/GroupingToggleButtons/GroupingToggleButtons.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-8058350007745800715?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/8058350007745800715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/09/grouping-and-checkboxes-in-wpf.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8058350007745800715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8058350007745800715'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/09/grouping-and-checkboxes-in-wpf.html' title='Grouping and Checkboxes in WPF'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-7611044614001987932</id><published>2009-08-20T17:09:00.001-07:00</published><updated>2009-08-20T17:09:40.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Expression Studio'/><title type='text'>Expression Design – Layer Options</title><content type='html'>&lt;p&gt;I am very much NOT a designer but, on occasion I play with the Expression Design tool to do simple vector graphics that I can use in WPF applications.&lt;/p&gt;  &lt;p&gt;Today I found myself building a simple “add” icon. That looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_MRQ9Z0kgSJI/So3lnjNH6xI/AAAAAAAABGU/MMCiqMcqyoY/s1600-h/AddIcon%5B1%5D%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="AddIcon[1]" border="0" alt="AddIcon[1]" src="http://lh6.ggpht.com/_MRQ9Z0kgSJI/So3loBbcvSI/AAAAAAAABGY/P-tlAU4vqPg/AddIcon%5B1%5D_thumb.png?imgmax=800" width="243" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When playing around in the layers dialog I found a little hidden setting call “Layer rendering style”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_MRQ9Z0kgSJI/So3loRNRWaI/AAAAAAAABGc/VsWVGVXb3SA/s1600-h/LayerRenderStyle%5B1%5D%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="LayerRenderStyle[1]" border="0" alt="LayerRenderStyle[1]" src="http://lh5.ggpht.com/_MRQ9Z0kgSJI/So3lohetfLI/AAAAAAAABGg/nqgwmlIp-lY/LayerRenderStyle%5B1%5D_thumb.png?imgmax=800" width="218" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;What I found is that this lets you modify the display quality of your objects on a given layer. The three options you have are Path, Wireframe, and Preview. According to &lt;a href="http://msdn.microsoft.com/en-us/library/cc294643.aspx" target="_blank"&gt;MSDN&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;“Changing the display quality setting does not affect your final output, but can help in navigating your document and selecting paths. For example, if you have very complex paths, a lower display quality can speed up screen redraw on a slower computer”&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The linked MSDN page shows examples of the three different display qualities. For example, if I take my Add Icon and change the display quality to wireframe it looks like this&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_MRQ9Z0kgSJI/So3lpMTyHwI/AAAAAAAABGk/shehIU66lN4/s1600-h/WireFrameAddIcon%5B1%5D%5B2%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="WireFrameAddIcon[1]" border="0" alt="WireFrameAddIcon[1]" src="http://lh5.ggpht.com/_MRQ9Z0kgSJI/So3lpdoefBI/AAAAAAAABGo/iklUB33CLN8/WireFrameAddIcon%5B1%5D_thumb.png?imgmax=800" width="244" height="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This seems like a handy option to have, especially if you have very complex paths or a ton of different layers. Changing to wireframe could speed up rendering performance and reduce the amount of visual noise on the screen.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-7611044614001987932?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/7611044614001987932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/08/expression-design-layer-options.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7611044614001987932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7611044614001987932'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/08/expression-design-layer-options.html' title='Expression Design – Layer Options'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-3049680536173976841</id><published>2009-08-14T09:15:00.001-07:00</published><updated>2009-08-14T09:15:09.881-07:00</updated><title type='text'>RE: All Programming is web programming?</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In a recent &lt;a href="http://www.codinghorror.com/blog/archives/001296.html" target="_blank"&gt;post&lt;/a&gt; @ Coding Horror, Jeff Atwood explains his views on the future of software development. He makes the claim that “All programming is web programming.”&lt;/p&gt;  &lt;p&gt;He has some solid points about the benefits of the web deployment model and the downside of the traditional desktop application. However, he seems to blur the lines on what he calls “web programming.” &lt;/p&gt;  &lt;p&gt;In his statement that “all programming will be web programming” he seems to define web programming as anything that has a web front end? &lt;/p&gt;  &lt;p&gt;Then, when he talks about crappy web programming and crappy web developers he seems to be talking about JavaScript and html hackers. I agree with him the web front end world is not a fun place to be. The development experience is frustrating and the tooling is kludgy.&lt;/p&gt;  &lt;p&gt;However, lets not forget that there is a ton of “back-end” development that is involved in “web development.” With separation patterns like MVP, MVC etcetera the crappy part of web development is abstracted away. &lt;/p&gt;  &lt;p&gt;So I think he has a point that more and more applications have a web presence (i.e Web front end, web services) but there is still a fair amount of &lt;strong&gt;software&lt;/strong&gt; development that has to take place to make it work.&lt;/p&gt;  &lt;p&gt;When I am writing software I try, as much as possible, not to concern myself with what the front end technology will be. Following patterns like MVP,MVC, MVVM , MVWhateverYouWantToCallIt allows your code to be UI agnostic and removes as much code as possible from the specific UI platform. &lt;/p&gt;  &lt;p&gt;At that point, to me, coding is coding. Whether I am writing a “web” system or not, there are still hard problems to solve and challenges to overcome.&lt;/p&gt;  &lt;p&gt;With the advent of declarative desktop UI technology like &lt;a href="http://windowsclient.net/" target="_blank"&gt;WPF&lt;/a&gt; there will undoubtedly be “bad” desktop UI developers just like there are “bad” web UI developers. &lt;/p&gt;  &lt;p&gt;Abstracting the hard problems away from the UI mitigates these issues and allows developers to focus on code period.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-3049680536173976841?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/3049680536173976841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/08/re-all-programming-is-web-programming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/3049680536173976841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/3049680536173976841'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/08/re-all-programming-is-web-programming.html' title='RE: All Programming is web programming?'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-8062417445047053529</id><published>2009-08-05T16:30:00.001-07:00</published><updated>2009-08-05T16:30:15.757-07:00</updated><title type='text'>Expression Encoder 3 Screen Capture</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Expression encoder 3 screen capture is a new product in the expression suite that is aimed at simplifying screen capture and screen cast production.&lt;/p&gt;  &lt;p&gt;For anyone who has done screen casts before you have likely used Camtasia. The early versions of Camtasia were a bit confusing and clunky to work with, but they were still the best option out there for quickly putting together screencasts. The most recent version of the Camtasia product has really improved and is a fine product. &lt;/p&gt;  &lt;p&gt;I am glad to see Microsoft jump into this area and develop a competing product. If nothing else this will spur competition and really drive the feature set of both products further.&lt;/p&gt;  &lt;p&gt;Where Expression Encoder Screen Capture really seems to excel is in Hi definition video capture and in general screen capture performance. From the &lt;a href="http://blogs.msdn.com/expressionencoder/"&gt;Expression Encoder blog&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;“One of the benefits of our new implementation is that we capture to a light weight intermediate CODEC, developed by Microsoft Research, rather than attempting to capture and encode directly to VC-1 or H.264.&amp;#160; This leaves more of the CPU available for the application you are capturing.” &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;What I really like about ESC (HA get it.. &lt;strong&gt;E&lt;/strong&gt;ncoder &lt;strong&gt;S&lt;/strong&gt;creen &lt;strong&gt;C&lt;/strong&gt;apture… ok enough nerd humor) is the selection model is very smooth. When I want to capture just one window to record it is very easy to isolate that window and then start recording.&lt;/p&gt;  &lt;p&gt;The post production workflow is very nice too. Since you have Expression Encoder installed as well you are able to open your captured video directly in Expression Encoder and then you have the full power of the encoding tool to make your video “distribution friendly”&lt;/p&gt;  &lt;p&gt;You can see a screen cast that I produced using ESC &lt;a href="http://www.bradcunningham.net/2009/08/expression-web-3-super-preview.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I think it is a very neat new tool in the Expression Studio 3 release and well worth checking out if you are you need to produce high quality screencasts with a streamlined post processing operation.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-8062417445047053529?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/8062417445047053529/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/08/expression-encoder-3-screen-capture.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8062417445047053529'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8062417445047053529'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/08/expression-encoder-3-screen-capture.html' title='Expression Encoder 3 Screen Capture'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-1650944670600546927</id><published>2009-08-04T22:05:00.001-07:00</published><updated>2009-08-05T15:55:24.848-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Expression Studio'/><title type='text'>Expression Web 3 Super Preview:</title><content type='html'>&lt;p&gt;I just started playing with Expression Studio 3 today and have already stumbled upon 2 very cool new tools. The first of which is Expression Web 3 Super Preview.&lt;/p&gt;  &lt;p&gt;This new program lets you load a web page in two different browsers at once and compare side by side differences. There are a few very nice compare methods that let you spilt the screens and select specific regions of the screen and easily isolate an area in both browsers.&lt;/p&gt;  &lt;p&gt;The best compare style of all though is overlay. This take both pages and layers them on top of each other and adjusts the transparency so you can see the layout differences of both pages. This is hard to explain with showing you so I have created a simple screencast that demonstrates the functionality. &lt;/p&gt; &lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5948446&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=5948446&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;  &lt;p&gt;&lt;a href="http://vimeo.com/5948446"&gt;Expression Web 3 Super Preview&lt;/a&gt; from &lt;a href="http://vimeo.com/bradcunningham"&gt;Brad Cunningham&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;(&lt;strong&gt;NOTE: &lt;/strong&gt;Vimeo downsampled the video when I uploaded :( If you want a higher quality version you can download it from &lt;a href="http://BradCunningham.net/Video/SuperWebPreview.wmv"&gt;here&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;In this screencast I load up my blog in the super preview tool.&amp;#160; The left hand panel will load using Firefox 3.0.12 and the right hand panel will load up using IE6.&lt;/p&gt;  &lt;p&gt;Then I switch the highlighting mode to “Lights out mode.” This creates&amp;#160; a shadow box like effect on the page so you can visually isolate aspects of the page. I select something on the left hand side (in Firefox) and you can see the corresponding element in the right hand pane (IE 6). You can see already how the two browsers render spacing differently. You can see in the bottom left corner there is a dialog that shows the width and height of the highlighted element and the Left and Top as well. you can see in the IE panel how it shows the Left and Top in red, indicating a difference from Firefox. &lt;/p&gt;  &lt;p&gt;This is an amazingly valuable tool for any web designer IMO. &lt;/p&gt;  &lt;p&gt;Now for the crème de la crème. Overlay mode. I can switch the windows so they overlay each other and see all the visual difference at one time, visually, without clicking around or guessing. This is totally awesome. How useful it will be to web developers I don’t really know (I have renounced my former life as a web developer and now, only play one on TV) but man does it look cool! &lt;/p&gt;  &lt;p&gt;I will have a follow up post discussing the other cool new tool, Expression Encoder 3 Screen Capture, in the near future&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-1650944670600546927?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/1650944670600546927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/08/expression-web-3-super-preview.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1650944670600546927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1650944670600546927'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/08/expression-web-3-super-preview.html' title='Expression Web 3 Super Preview:'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-4927417261853222784</id><published>2009-08-04T10:55:00.001-07:00</published><updated>2009-08-04T10:55:39.309-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Dev Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><title type='text'>Hard drive clean up</title><content type='html'>&lt;p&gt;From time to time I find myself cleaning up stale files on my hardrive to conserve space. Yeah space is cheap but I am anal about keeping a clean machine. &lt;/p&gt;  &lt;p&gt;This cleanup process is usually two step. First I will go through all my installed programs and uninstall things that I haven’t used in a long time or I no longer need. Being a developer I am constantly installing software and testing out beta products etc.. This results in a long list of random bits of software that often times is only useful for a short period of time then I will never us it again.&lt;/p&gt;  &lt;p&gt;Once I uninstall all the unused programs I run &lt;a href="http://www.jam-software.com/freeware/index.shtml"&gt;TreeSizeFree&lt;/a&gt;. I am not even sure how I found this little utility but I have been using it for years with great success. It does a simple scan of your drive and will quickly show you where all your space is being taken up. &lt;/p&gt;  &lt;p&gt;In my latest cleanup effort I noticed that a lot of space was being consumed by my TestResults directory that Visual Studio creates for each test run.&lt;/p&gt;  &lt;p&gt;Here is a screen cap of just two TestResult directories.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_MRQ9Z0kgSJI/Snh2FYWH8QI/AAAAAAAABFs/MqlOMTL2fWU/s1600-h/TestResults%5B1%5D%5B2%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TestResults[1]" border="0" alt="TestResults[1]" src="http://lh5.ggpht.com/_MRQ9Z0kgSJI/Snh2FnqiGjI/AAAAAAAABFw/hg4FU73QwRs/TestResults%5B1%5D_thumb.png?imgmax=800" width="203" height="67" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;So I went through and cleaned up these folders since I did not need the historical results information any longer. &lt;/p&gt;  &lt;p&gt;I also went into Visual Studio and changed the TestRun history to save only the last 5 Test Runs instead of the default of 10 test runs. This keeps the folder bloat down and, for me, is enough history.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_MRQ9Z0kgSJI/Snh2GIGLcII/AAAAAAAABF0/VWWhSojN6yA/s1600-h/TestResultsHistory%5B2%5D%5B8%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TestResultsHistory[2]" border="0" alt="TestResultsHistory[2]" src="http://lh4.ggpht.com/_MRQ9Z0kgSJI/Snh2GvgJXdI/AAAAAAAABF4/_AHW_eSN1Zg/TestResultsHistory%5B2%5D_thumb%5B6%5D.png?imgmax=800" width="569" height="346" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-4927417261853222784?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/4927417261853222784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/08/hard-drive-clean-up.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/4927417261853222784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/4927417261853222784'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/08/hard-drive-clean-up.html' title='Hard drive clean up'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-8317339896387023164</id><published>2009-07-22T08:30:00.001-07:00</published><updated>2009-08-04T10:32:08.012-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Touch'/><category scheme='http://www.blogger.com/atom/ns#' term='Speaking'/><title type='text'>.NET Rocks Interview</title><content type='html'>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;I just had the pleasure of doing a &lt;a href="http://www.dotnetrocks.com/"&gt;.NET rocks&lt;/a&gt; podcast with &lt;a href="http://www.intellectualhedonism.com/"&gt;Carl&lt;/a&gt; and &lt;a href="http://www.campbellassociates.ca/blog/"&gt;Richard&lt;/a&gt;. &lt;strike&gt;It will be show #469 and should be available on August 4, 2009&lt;/strike&gt; (&lt;strike&gt;I will update this post with a link when it becomes available&lt;/strike&gt;). It is show #469 and you can listen to it &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=469"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The show is about touch based computing, touch based hardware, Surface, Win7, social computing and Richard’s Touchsmart in his kitchen. Good times. &lt;/p&gt;  &lt;p&gt;We even dive into the risqué topic of “social touching”…..&lt;/p&gt;  &lt;p&gt;Check it out.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-8317339896387023164?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/8317339896387023164/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/07/net-rocks-interview.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8317339896387023164'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/8317339896387023164'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/07/net-rocks-interview.html' title='.NET Rocks Interview'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-2585773575885160632</id><published>2009-07-16T11:49:00.001-07:00</published><updated>2009-07-26T10:32:18.316-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Blend'/><title type='text'>Blend 3 improvements</title><content type='html'>&lt;p&gt;I am trying to put Blend 3 through its paces and here are a few random improvements I have found.&lt;/p&gt;  &lt;p&gt;I will keep updating this post as I find more&lt;/p&gt;  &lt;h3&gt;&lt;b&gt;Attribute Defaults&lt;/b&gt;&lt;/h3&gt;  &lt;p&gt;Setting an attribute to its default value (e.g. Setting HorizontalAlignment&amp;#160; to Stretch) will remove the value from the XAML. Previously you had to click on the Advanced Property options and chose reset it you wanted Blend to delete the auto generated XAML. Now, it seems, Blend it smart enough to not explicitly set the attribute.&lt;/p&gt;  &lt;h3&gt;&lt;b&gt;Padding, Margin etc..&lt;/b&gt;&lt;/h3&gt;  &lt;p&gt;If you set a margin or padding value to all the same value in the Property Panel it will generate the short hand attribute syntax for you. So setting each margin to -10 in the Property panel will generate Margin=”-10” in the XAML. Again, it seems it is getting smarter about generating XAML.&lt;/p&gt;  &lt;h3&gt;Asset Library&lt;/h3&gt;  &lt;p&gt;Searching for assets in the library finally searches across multiple categories. The results are nicely displayed so you can see what was found in each category.&amp;#160; So now, for example, you can search for Surface Controls using the library without having to switch to the Custom Controls category first.&lt;/p&gt;  &lt;h3&gt;Design Time Height and Width&lt;/h3&gt;  &lt;p&gt;If you set a Width or Height property to Auto it will show you the design time value in parentheses after the word Auto. It will do something like Auto(756).&lt;/p&gt;  &lt;p&gt;I find this extremely useful when designing items controls with custom data templates. You can see how much space it thinks it needs to take up to fit the content, while leaving your items control set to Auto.&lt;/p&gt;  &lt;h3&gt;Pack Syntax for Image Brushes&lt;/h3&gt;  &lt;p&gt;When you add an image to your project and make an ImageBrush resource from it. Blend with generate the proper pack syntax (component syntax) to reference the image.&lt;/p&gt;  &lt;h3&gt;ItemContainerStyle&lt;/h3&gt;  &lt;p&gt;Finally! The gods have spoken. When working with ItemsControls, you can now right click, select “Edit additional Templates” and select ItemContainerStyle. This was one of the most annoying quirks of Blend 2 for me. Previously you had to select the Items control and then go up to the Object menu and select “Edi additional styles, then select item container style. Now that is it in the context menu for ItemsControl it makes the work flow much more fluid.&lt;/p&gt;  &lt;p&gt;Also, as a side note, I notice that the navigation in and out of the ItemContainerStyle seems to be improved. In Blend 2 there was strange behavior when you were editing ItemContainerStyle and moving back and fourth between the Style and the ControlTemplate. It doesn’t appear to be entirely fixed, but I am notice less of these weird issues were you are jumped around to the wrong object when trying to switch back and fourth.&lt;/p&gt;  &lt;h3&gt;Effect&lt;/h3&gt;  &lt;p&gt;Effect has been moved up to the the top level (above the expander) for the Appearance section. This is a nice touch, as I find myself using Effects often. Still, more times than not I use the search to filter the property list anyway, but having at the top level makes it faster.&lt;/p&gt;  &lt;p&gt;That being said, I wish there was a way to customize which properties were shown. Being able to configure my own default property panel view would be great. Then I could put just the properties I use most often in the top panels and hide the other stuff in the expanders. For instance, in brushes panel I very rarely use the OpacityMask brush so I would it to save space, Likewise with the ZIndex in the Layout panel. Maybe in Blend 4?&lt;/p&gt;  &lt;h3&gt;Tools | Options&lt;/h3&gt;  &lt;p&gt;There a few new settings you can change under the Tools | Options menu. &lt;/p&gt;  &lt;h2&gt;Units&lt;/h2&gt;  &lt;p&gt;You can now change the default unit of measure (between pixels and points). I can this being useful when working with Photoshop or Illustrator files and importing them in to Blend.&lt;/p&gt;  &lt;h2&gt;Zoom&lt;/h2&gt;  &lt;p&gt;You can change the default behavior for MouseWheel zoom (between Just mouse wheel, Alt + MouseWheel, and Ctrl+ MouseWheel). I have been waiting for tihs so I can make Blend behave the same as Illustrator in this regard. &lt;/p&gt;  &lt;h2&gt;&lt;strong&gt;Effect Rendering&lt;/strong&gt;&lt;/h2&gt;  &lt;p&gt;You can turn on and off the rendering of effects (not sure why you would want to this, except maybe to increase performance?) The other sneaky setting here is the zoom threshold level. Setting this causes effects to &lt;strong&gt;not &lt;/strong&gt;be rendered beyond this threshold. This has tripped me up a few times already. When zooming way in on a button for instance, all of sudden my drop shadow effect disappears? Again, I suppose this feature is for performance reasons.&lt;/p&gt;  &lt;h2&gt;Annotations&lt;/h2&gt;  &lt;p&gt;You can now set default annotations properties for your documents, and optionally show them on the Artboard. You can set the Author name and Author initials.&lt;/p&gt;  &lt;h2&gt;SketchFlow&lt;/h2&gt;  &lt;p&gt;Finally there settings specific to SketchFlow documents. I haven’t dove too deeply into Skecthflow yet, but I will in the near future and have a new post strictly about SketchFlow.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-2585773575885160632?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/2585773575885160632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/07/blend-3-improvements.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2585773575885160632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2585773575885160632'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/07/blend-3-improvements.html' title='Blend 3 improvements'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-2543012020437773897</id><published>2009-07-06T17:05:00.001-07:00</published><updated>2009-07-08T14:26:04.406-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Touch'/><category scheme='http://www.blogger.com/atom/ns#' term='Speaking'/><title type='text'>geekSpeak recording on Channel 9</title><content type='html'>&lt;p&gt;&lt;a href="http://www.bradcunningham.net/2009/05/geekspeak-interview.html" target="_blank"&gt;Recently&lt;/a&gt; I recorded a &lt;a href="http://channel9.msdn.com/shows/geekSpeak/" target="_blank"&gt;geekSpeak&lt;/a&gt; interview on Touch Based computing and the general &lt;a href="http://en.wikipedia.org/wiki/Natural_User_Interface" target="_blank"&gt;NUI&lt;/a&gt; paradigm shift.&lt;/p&gt;&lt;p&gt;I just noticed that the interview has been uploaded to Channel 9 now so if you missed it you can check it out here&lt;/p&gt;&lt;p&gt;&lt;a title="http://channel9.msdn.com/shows/geekSpeak/geekSpeak-Recording-Touch-based-Computing-with-Brad-Cunningham/" href="http://channel9.msdn.com/shows/geekSpeak/geekSpeak-Recording-Touch-based-Computing-with-Brad-Cunningham/"&gt;http://channel9.msdn.com/shows/geekSpeak/geekSpeak-Recording-Touch-based-Computing-with-Brad-Cunningham/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;It is a talk show based podcast so there isn’t much video to pay attention too but you can listen to it while you work (if you are that geeky :) ) &lt;/p&gt;&lt;p&gt;If you listen to it and think it is awesome let me know (if you think it really sucks you can let me know too :( ) &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-2543012020437773897?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/2543012020437773897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/07/geekspeak-recording-on-channel-9.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2543012020437773897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2543012020437773897'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/07/geekspeak-recording-on-channel-9.html' title='geekSpeak recording on Channel 9'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-657878769677630792</id><published>2009-07-03T12:04:00.001-07:00</published><updated>2009-07-03T12:04:14.974-07:00</updated><title type='text'>TextTrimming in Silverlight 2</title><content type='html'>&lt;p&gt;In a &lt;a href="http://www.bradcunningham.net/2008/12/think-outside-textbox.html" target="_blank"&gt;previous post&lt;/a&gt; I found myself hacking around in the Silverlight 2 trying to emulate drop shadows on text blocks (something that is natively supported in WPF but missing in Silverlight 2)&lt;/p&gt;  &lt;p&gt;Once again, I find myself trying to emulate functionality that is natively supported in WPF and again it is related to TextBlocks.&lt;/p&gt;  &lt;p&gt;In WPF when you have a TextBlock whose text could extend beyond the available space you have the option to trim the text using a specified TextTrimming setting. To do this in WPF you would set the TextTrimming property of the TextBlock element and be done. Something like this:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;TextBlock Text=&amp;quot;A really really long string that should be trimmed&amp;quot;&lt;br /&gt;                   TextTrimming=&amp;quot;CharacterEllipsis&amp;quot; /&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In Silverlight there is no such property on a TextBlock. So I created a quick and dirty implementation that works (for the most part)&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I created a new UserControl called TrimmingTextBlock. The XAML for this control looks like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&amp;lt;UserControl x:Class=&amp;quot;TextTrimming.TrimmingTextBlock&amp;quot;&lt;br /&gt;    xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot; &lt;br /&gt;    xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot; &amp;gt;&lt;br /&gt;    &amp;lt;TextBlock x:Name=&amp;quot;TrimmedTextBlock&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;All the “magic” (a.k.a hacking) happens in the code behind. I wanted the consumer of the control to be able to bind to a Text property, just like a normal TextBlock so I created a custom dependency property called Text&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;private static readonly DependencyProperty TextProperty = DependencyProperty.Register(&amp;quot;Text&amp;quot;,&lt;br /&gt;typeof(String),&lt;br /&gt;typeof(TrimmingTextBlock),&lt;br /&gt;new PropertyMetadata(String.Empty,OnTextChanged));&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I need to display trimmed text but I still wanted the “Text” property of my control to maintain the original string. Trimming is only a display issue and shouldn’t impact the underlying data. So I created a second private dependency property called TrimmedText where I will store the display version of the string.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;private static readonly DependencyProperty TrimmedTextProperty = DependencyProperty.Register(&lt;br /&gt;&amp;quot;TrimmedText&amp;quot;,&lt;br /&gt;typeof(String),&lt;br /&gt;typeof(TrimmingTextBlock),&lt;br /&gt;new PropertyMetadata(String.Empty, OnTrimmingTextChanged));&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So the first step is to make sure the TrimmedText property gets the value that is bound to the Text property. I do this in the OnTextChanged method (this is fired whenever the Text dependency property is changed). In the changed method I am getting an instance of my control and finding the TextBlock element and setting it’s text property to the new value.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&lt;br /&gt;{&lt;br /&gt;    var tb = d as TrimmingTextBlock;&lt;br /&gt;    if (tb != null)&lt;br /&gt;    {&lt;br /&gt;        tb.TrimmedTextBlock.Text = e.NewValue.ToString();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Now that the data is wired up correctly I have to do the actual trimming. In the ArrangeOverride method of my control I call my TrimText method&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;protected override Size ArrangeOverride(Size finalSize)&lt;br /&gt;{&lt;br /&gt;    TrimText(this);&lt;br /&gt;    return base.ArrangeOverride(finalSize);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In TrimText I get the ActualWidth of the TextBlock. Since I have set the Text property already the ActualWidth will be the width in pixels that is needed to display the specified string of text.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I compare this ActualWidth to the DesiredWidth, that is the width that is available to the TextBlock. If the text is larger then the available space, that is if the ActualWidth is greater than the DesiredWidth, I need to trim.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;My trimming implementation is simplistic but seems to work. I chop off one character at a time from the end of the string and then update the TextBlock with the new value. This causes a measure and arrange pass to fire which will call my trim method again and we can re-check the width.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;I continue cutting off one character at time until the text will fit. Here is what the Trim method looks like:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: csharp;"&gt;private static void TrimText(TrimmingTextBlock block)&lt;br /&gt;{&lt;br /&gt;    //Check the desired size of the text block and the actual size and trim accordingly&lt;br /&gt;    var actualWidth = block.TrimmedTextBlock.ActualWidth;&lt;br /&gt;    var desiredWidth = Double.MinValue;&lt;br /&gt;&lt;br /&gt;    if (desiredWidth == Double.MinValue)&lt;br /&gt;    {&lt;br /&gt;        desiredWidth = block.TrimmedTextBlock.DesiredSize.Width;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (desiredWidth &amp;lt; actualWidth)&lt;br /&gt;    {&lt;br /&gt;        //Trim&lt;br /&gt;        String trimmedText = block.TrimmedTextBlock.Text;&lt;br /&gt;&lt;br /&gt;        if (!trimmedText.Contains(&amp;quot;…&amp;quot;))&lt;br /&gt;            trimmedText += &amp;quot;…&amp;quot;;&lt;br /&gt;&lt;br /&gt;        trimmedText = String.Concat(trimmedText.Substring(0, trimmedText.IndexOf(&amp;quot;…&amp;quot;) - 1), &amp;quot;…&amp;quot;);&lt;br /&gt;        block.SetValue(TrimmedTextProperty, trimmedText);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This approach seems to work in most cases. For my purposes it does the job. This isn’t the most optimized code as it can cause a ton of Measure and Arrange operations. In fact in Silverlight 2 there is a known bug (which is fixed in SL3 beta1) that you cannot have more than 250 layout operations on one page. &lt;a href="http://silverlight.net/forums/t/39037.aspx" target="_blank"&gt;See this thread&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Because of this bug this solution doesn’t really scale that nicely if you have the need for a bunch of TrimmingTextBlocks on one page. Or if you have a really long string that could cause more than 250 layout recursions.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This code could be optimized so that large strings cause fewer layout passes by intelligently removing more than one character at a time. But for me this works for now.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can get the code with a few examples of usage from &lt;a href="http://BradCunningham.net/SourceCode/TextTrimming/TextTrimming.zip" target="_blank"&gt;here&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-657878769677630792?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/657878769677630792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/07/texttrimming-in-silverlight-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/657878769677630792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/657878769677630792'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/07/texttrimming-in-silverlight-2.html' title='TextTrimming in Silverlight 2'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-1174517785103536412</id><published>2009-06-22T10:42:00.001-07:00</published><updated>2009-06-22T10:42:52.460-07:00</updated><title type='text'>Two sessions for Code Camp this weekend</title><content type='html'>&lt;p&gt;I have two sessions scheduled for the &lt;a href="http://www.socalcodecamp.com/" target="_blank"&gt;Code Camp&lt;/a&gt; event in San Diego this weekend&lt;/p&gt;  &lt;p&gt;Touch 101&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.socalcodecamp.com/session.aspx?sid=e927884d-6bb6-4e13-9554-ee426e573f0f"&gt;http://www.socalcodecamp.com/session.aspx?sid=e927884d-6bb6-4e13-9554-ee426e573f0f&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;XAML Panel discussion&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.socalcodecamp.com/session.aspx?sid=4046c382-190d-40f6-b86b-af0dd307b9ae"&gt;http://www.socalcodecamp.com/session.aspx?sid=4046c382-190d-40f6-b86b-af0dd307b9ae&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If your interested come and check it out. It’s free.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-1174517785103536412?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/1174517785103536412/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/06/two-sessions-for-code-camp-this-weekend.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1174517785103536412'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1174517785103536412'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/06/two-sessions-for-code-camp-this-weekend.html' title='Two sessions for Code Camp this weekend'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-1455885260213471488</id><published>2009-06-16T14:23:00.001-07:00</published><updated>2009-06-16T14:23:57.743-07:00</updated><title type='text'>Binding to custom attached properties</title><content type='html'>&lt;p&gt;Another quick post. In an effort to blog more I am trying to blog quick snippets I come across instead of full blown manifestos. &lt;/p&gt;  &lt;p&gt;Colleagues of mine at &lt;a href="http://www.interknowlogy.com"&gt;InterKnowlogy&lt;/a&gt; came across an interesting binding edge case the other day and I thought it would make a decent post. In the past I have needed to bind to attached properties (although it has been rare). Typically I was doing something like this :&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;DockPanel Height=&amp;quot;100&amp;quot; Width=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock DockPanel.Dock=&amp;quot;Left&amp;quot;&lt;br /&gt;    Text=&amp;quot;{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock DockPanel.Dock=&amp;quot;Right&amp;quot;&lt;br /&gt;    Text=&amp;quot;{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock DockPanel.Dock=&amp;quot;Top&amp;quot;&lt;br /&gt;    Text=&amp;quot;{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}&amp;quot; /&amp;gt;&lt;br /&gt;    &amp;lt;TextBlock DockPanel.Dock=&amp;quot;Bottom&amp;quot;&lt;br /&gt;    Text=&amp;quot;{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}&amp;quot; /&amp;gt;&lt;br /&gt;&amp;lt;/DockPanel&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Where I am binding to the attached property “DockPanel.Dock.” The basic trick here is to add the parentheses around the path to indicate you are binding to an attached property.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The edge case we came across this past week was binding to a custom attached property. Something like this &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&amp;lt;TextBlock Custom:MyAttachedProperty.CustomString=&amp;quot;Some String&amp;quot; &lt;br /&gt;Text=&amp;quot;{Binding RelativeSource={RelativeSource Self}, Path=(MyAttachedProperty.CustomString)}&amp;quot; /&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Where I am binding to “MyAttachedProperty.CustomString.” This however doesn’t work as posted. It will throw and error stating it cannot find type MyAttachedProperty. The solution may be obvious to most but we were stuck on it for a few minutes.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You have to add the namespace prefix to the property in the binding in order for the Binding markup extension to be able to resolve the custom type and find the attached property.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So the example above is corrected like this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&amp;lt;TextBlock Custom:MyAttachedProperty.CustomString=&amp;quot;Some String&amp;quot; &lt;br /&gt;Text=&amp;quot;{Binding RelativeSource={RelativeSource Self}, Path=(Custom:MyAttachedProperty.CustomString)}&amp;quot; /&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Like I said, might be obvious to most but it isn’t something I had done before so it took a few minutes to discover the correct way to do it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-1455885260213471488?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/1455885260213471488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/06/binding-to-custom-attached-properties.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1455885260213471488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1455885260213471488'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/06/binding-to-custom-attached-properties.html' title='Binding to custom attached properties'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-2983140556688872788</id><published>2009-06-09T10:07:00.001-07:00</published><updated>2009-06-10T08:55:12.051-07:00</updated><title type='text'>Controlling Audio playback in XAML</title><content type='html'>&lt;p&gt;Just a quick post (mainly for my own reference). I had the need to do some simple audio playback in a WPF application recently and wanted to trigger the playback declaratively.&lt;/p&gt;  &lt;p&gt;In the&amp;#160; past any media playback I have done through code behind of some sort. In this scenario the audio files were going to be more dynamic and all I needed to perform was a simple play operation. I didn’t have the need to support pausing, fast forward, rewind, etc. Just play the clip.&lt;/p&gt;  &lt;p&gt;A little poking around on the &lt;a href="http://en.wikipedia.org/wiki/Series_of_tubes"&gt;tubes&lt;/a&gt; didn’t turn up much useful. Hence why I am posting this entry.&lt;/p&gt;  &lt;p&gt;I found that if you use the MediaElement control you can trigger it using a MediaTimline element in a BeginStoryboard action.&lt;/p&gt;  &lt;p&gt;First declare your MediaElement and simply give it an x:Name (don’t specify the source, LoadedBehavior, UnloadeBehavior etc..)&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;MediaElement x:Name=&amp;quot;mediaElement&amp;quot; /&amp;gt;&amp;#160; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Then wherever you want to trigger the animation (on a button click in my case) put the following event trigger&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml;"&gt;&amp;lt;Button.Triggers&amp;gt;&lt;br /&gt;    &amp;lt;EventTrigger RoutedEvent=&amp;quot;ButtonBase.Click&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;BeginStoryboard&amp;gt;&lt;br /&gt;            &amp;lt;Storyboard&amp;gt;&lt;br /&gt;                &amp;lt;MediaTimeline Source=&amp;quot;Resources\AudioFiles\easy.wma&amp;quot; Storyboard.TargetName=&amp;quot;mediaElement&amp;quot; /&amp;gt;&lt;br /&gt;            &amp;lt;/Storyboard&amp;gt;&lt;br /&gt;        &amp;lt;/BeginStoryboard&amp;gt;&lt;br /&gt;    &amp;lt;/EventTrigger&amp;gt; &lt;br /&gt;&amp;lt;/Button.Triggers&amp;gt;&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-2983140556688872788?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/2983140556688872788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/06/controlling-audio-playback-in-xaml.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2983140556688872788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/2983140556688872788'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/06/controlling-audio-playback-in-xaml.html' title='Controlling Audio playback in XAML'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-7620939497249140701</id><published>2009-05-20T14:41:00.001-07:00</published><updated>2009-05-20T15:54:56.578-07:00</updated><title type='text'>geekSpeak interview</title><content type='html'>&lt;p&gt;I am going to be giving a live MSDN webcast as part of the geekSpeak series. The discussion will be focused around Touch based development in general. More specifically we will be covering touch based hardware implementations and gestural interface design. &lt;/p&gt;  &lt;p&gt;If you are interested in joining in on the discussion you can register here&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032416182&amp;amp;Culture=en-US"&gt;http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032416182&amp;amp;Culture=en-US&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;best of all it’s FREE!&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The discussion will be hosted by &lt;a href="http://blogs.msdn.com/socaldevgal/"&gt;Lynn Langit&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/mithund/"&gt;Mithun Dhar&lt;/a&gt;. Many thanks to Lynn for inviting me to do this event.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-7620939497249140701?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/7620939497249140701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/05/geekspeak-interview.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7620939497249140701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/7620939497249140701'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/05/geekspeak-interview.html' title='geekSpeak interview'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7601250593789026634.post-1682690305563374532</id><published>2009-04-29T10:10:00.001-07:00</published><updated>2009-04-29T10:10:35.429-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Surface'/><category scheme='http://www.blogger.com/atom/ns#' term='Win7'/><category scheme='http://www.blogger.com/atom/ns#' term='Touch'/><category scheme='http://www.blogger.com/atom/ns#' term='Speaking'/><title type='text'>Touch 101 Talk – San Diego .NET user group</title><content type='html'>&lt;p&gt;Thanks to everyone that came out to my talk last night. We had a good time discussing touch based development and gestural interfaces.&lt;/p&gt;  &lt;p&gt;You can download the slide deck &lt;a href="http://bradcunningham.net/SlideDecks/Touch101/TouchDevelopment101.zip"&gt;here&lt;/a&gt; if you are interested.&lt;/p&gt;  &lt;p&gt;Here are a handful of links that I showed during the talk. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/surface/"&gt;http://www.microsoft.com/surface/&lt;/a&gt; &lt;a href="http://code.msdn.microsoft.com/WindowsTouch"&gt;http://code.msdn.microsoft.com/WindowsTouch&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.interknowlogy.com/"&gt;http://www.interknowlogy.com/&lt;/a&gt; &lt;a href="http://silverlight.interknowlogy.com/Videos/Surface/default.html"&gt;http://silverlight.interknowlogy.com/Videos/Surface/default.html&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.perceptivepixel.com/"&gt;http://www.perceptivepixel.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://vimeo.com/4206140"&gt;http://vimeo.com/4206140&lt;/a&gt; &lt;a href="http://idlemode.com/2009/04/10/design-considerations-for-touch-ui/"&gt;http://idlemode.com/2009/04/10/design-considerations-for-touch-ui/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.designinggesturalinterfaces.com/"&gt;http://www.designinggesturalinterfaces.com/&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7601250593789026634-1682690305563374532?l=www.bradcunningham.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/1682690305563374532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.bradcunningham.net/2009/04/touch-101-talk-san-diego-net-user-group.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1682690305563374532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7601250593789026634/posts/default/1682690305563374532'/><link rel='alternate' type='text/html' href='http://www.bradcunningham.net/2009/04/touch-101-talk-san-diego-net-user-group.html' title='Touch 101 Talk – San Diego .NET user group'/><author><name>Brad</name><uri>http://www.blogger.com/profile/08574023764643076667</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='04700906054830375896'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>