<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Steve-Holstad/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Steve-Holstad/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Steve-Holstad/Posts</link>
    <language>en</language>
    <pubDate>Sun, 26 May 2013 00:52:23 GMT</pubDate>
    <lastBuildDate>Sun, 26 May 2013 00:52:23 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>2</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Twitterlight: A Silverlight Twitter client</title>
      <description><![CDATA[<span id="c4fmetadata">
<table cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td width="50"><img height="50" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/7883342/Thumb1.jpg" width="50"></td>
<td><span class="entry_description">Twitter, using simple SMS length messages, has changed how people stay connected.&nbsp; Here's how to build a Silverlight web client to access the Twitter API and display your tweets in a layout of your choosing.&nbsp; The Twitterlight
 code provides a solid starting point for communicating with any RESTful service interface, and you'll also see how to overcome Silverlight's cross-domain call limitations by leveraging a local proxy web service.</span></td>
</tr>
<tr>
<td colspan="2">
<div class="entry_author">Steve Holstad</div>
<div class="entry_company"><a href="http://blogs.claritycon.com/blogs/steve_holstad/archive/2008/01/08/twitterlight-silverlight-twitter-mashup-with-componentone-sapphire-controls.aspx" target="_blank">Steve's Blog</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Intermediate</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
Greater than 10 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input">Microsoft Visual Studio,
<a href="http://msdn2.microsoft.com/en-us/silverlight/bb419317.aspx" target="_blank">
Silverlight 2.0 Alpha September Refresh</a>, (NEW) <a href="http://www.microsoft.com/silverlight/resources/installationFiles.aspx?v=2.0" target="_blank">
Silverlight 2.0 Beta 1</a>, <a href="http://labs.componentone.com/Sapphire/" target="_blank">
ComponentOne Sapphire Toolset</a></span></div>
<div class="entry_details"><b>Hardware: </b></div>
</td>
</tr>
</tbody>
</table>
</span>
<p><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/7883342/Screenshot2.jpg"></p>
<h3>Developer Update (5/18/2009)</h3>
<p><strong>The Silverlight 2.0 RTW Source Code is available at the link below.&nbsp; Please note that the RTW version contains no reference to the Sapphire controls used during the SL 2 Beta.</strong></p>
<p><a title="Twitterlight_v22.zip" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/7883342/Twitterlight_v22.zip">Twitterlight_v22.zip</a></p>
<p>I am planning to create a new Twitterlight version for Silverlight 3, so I'm sad to say this code base won't be updated past 2.0.&nbsp; Thanks for the feedback and support!</p>
<h3>Developer Update (4/1/2008)</h3>
<p><strong>Twitterlight has been updated to the newest Silverlight release: Silverlight 2.0 Beta 1</strong>.&nbsp; You'll need this runtime installed in order to run the app at
<a href="http://www.twitterlight.com" target="_blank">twitterlight.com</a>.&nbsp; Don't forget that to compile the code, you must download, install and add references to the appropriate ComponentOne Sapphire control set.</p>
<h3>Introduction</h3>
<p>I've become a big believer in the power of Twitter to keep an informal social network of like-minded folks loosely yet immediately connected.&nbsp; Often times developers have a decent number of contacts they'd like to keep in contact with, but perhaps don't
 always have time to reach out one-on-one often enough.&nbsp; Twitter provides a mechanism which somehow gives that constantly connected &quot;feel&quot;.&nbsp; As a consultant that works at many sites, I wanted to create a web-based client to allow Twitterers like me to remain
 connected without the need for installing any applications on their current machine.&nbsp; Silverlight will give the UI more pop than the existing Twitter site, and provide features like auto-update and TinyURL support.</p>
<h3>Notes</h3>
<p>If you have a Twitter account, try the app at <a href="http://www.twitterlight.com/" target="_blank">
Twitterlight.com</a>.</p>
<p>The Twitterlight project is written using the Silverlight 2.0 Beta 1.&nbsp; Previously this article was published using the Silverlight 1.1 Alpha September Refresh.</p>
<p>The Twitterlight project consists of a Silverlight application (TwitterSL), a web site (TwitterSLServer) and a class library containing common controls (TwitterSL.Common).&nbsp;
</p>
<p>By now Silverlight is now infamous for its security setting which prevents cross-domain calls.&nbsp; What this means is that in order to serve external data, a Silverlight application must call to a web service hosted within the same domain.&nbsp; This proxy web service
 can then issue the post to the external data source (here the Twitter API), parse the result, and return back the result to the initial Silverlight code.&nbsp;&nbsp;&nbsp; Therefore the TwitterSLServer web site contains a local web service (TwitterWebService.asmx) to marshall
 the Twitter web requests, acting as a the proxy between Silverlight code and the Twitter API.</p>
<h3>How it all works</h3>
<p><strong>Silverlight application</strong> (<em>TwitterSL</em>): The Silverlight project lives and dies with the Page.xaml markup and Page.xaml.cs code-behind.&nbsp; This code creates the application shell, collects user authentication info, and provides the mechanism
 for posting new statuses to Twitter (including TinyURL support).&nbsp; TinyURL, btw, is a must-have for Twitter, because posts are limited to the length of SMS messages, ~140 characters.&nbsp; TinyURL replaces a full-sized link with a mini-me version of the link, giving
 you extra room to vent about Roger Clemens or Kanye West's Grammy speech.&nbsp; Sweet.</p>
<p>The Page.xaml.cs code maintains a reference to the local web service and issues all Twitter API web requests asynchronously to this proxy.&nbsp; When a response is returned, the XML snippet is parsed and mapped to a new instance of TwitControl, and inserted into
 the message container.&nbsp; The app allows users to toggle the type of response returned, from Public (all latest posts), Archive (your posts), Replies (directed at you), and the standard Friends (you and all your buddies).</p>
<p><strong>Control Toolset</strong> (<em>ComponentOne Sapphire</em>): I used ComponentOne's new Sapphire control toolset for this project.&nbsp; These controls add some nice functionality to a Silverlight project without forcing developers to create everything from
 scratch.&nbsp; I used C1's Label, LinkLabel and StackPanel to create the TwitControl, and the StackPanel and FlowPanel within Page.xaml to setup the layout of the application.&nbsp; I recommend trying these controls if you're starting out in Silverlight: a trial version
 is provided, and the support response was solid when I ran into a few minor issues.&nbsp; I'm excited to see the improvements to both Silverlight and the available control toolsets as they evolve together.&nbsp; One thing to note is that I created all third-party controls
 at runtime in order to avoid some VS designer issues, which should be corrected in the future.&nbsp;
</p>
<p><em>You'll need to download and install this toolset from the ComponentOne site, and add references to C1.Silverlight.dll in order to compile the project.</em></p>
<p>Here's how to add a few controls to the XAML (the sp.ReplacePlaceHolder call swaps out a Silverlight placeholder with the newly created StackPanel):</p>
<pre class="code"><span>C#:</span></pre>
<pre class="code"><span>///</span><span> </span><span>&lt;summary&gt;
</span><span>///</span><span> Builds third party controls dynamically at runtime
</span><span>///</span><span> </span><span>&lt;/summary&gt;
</span><span>private</span> <span>void</span> CreateComponentOneControls()
{
<span>    TextBlock</span> twitMessage = <span>new</span> <span>TextBlock</span>();
    twitMessage.Width = 290;
    twitMessage.FontSize = 11;
    twitMessage.Foreground = <span>new</span> <span>SolidColorBrush</span>(<span>Colors</span>.White);
    twitMessage.TextWrapping = <span>TextWrapping</span>.Wrap;
    _twitMessage = twitMessage;
            </pre>
<pre class="code">    ... other controls initialized...</pre>
<pre class="code">    twitTextPlaceholder = implementationRoot.FindName(<span>&quot;twitStackPanelPlaceholder&quot;</span>) <span>as</span> <span>Canvas</span>;
                        
    <span>C1StackPanel</span> sp = <span>new</span> <span>C1</span><span>StackPanel</span>();
    sp.IsHorizontal = <span>false</span>;
    sp.ReplacePlaceHolder(twitTextPlaceholder, <span>true</span>);
    sp.AutoSize = <span>AutoSize</span>.Both;
    sp.Padding = <span>new</span> <span>Thickness</span>(5, 5, 2, 5);
    sp.HorizontalAlignment = <span>Alignment</span>.Near;
    sp.VerticalAlignment = <span>Alignment</span>.Near;
    sp.ChildSpacing = <span>new</span> <span>Size</span>(2, 0);
                       
    sp.Children.Add(twitMessage);        
}</pre>
<pre class="code"><span>VB:</span></pre>
<pre class="code"><span>''' </span><span>&lt;summary&gt;
</span><span>''' Builds third party controls dynamically at runtime
</span><span>''' </span><span>&lt;/summary&gt;
</span><span>Private</span> <span>Sub</span> CreateComponentOneControls()
    <span>Dim</span> twitMessage <span>As</span> <span>New</span> TextBlock()
    twitMessage.Width = 290
    twitMessage.FontSize = 11
    twitMessage.Foreground = <span>New</span> SolidColorBrush(Colors.White)
    twitMessage.TextWrapping = TextWrapping.Wrap
    _twitMessage = twitMessage

    <span>...other controls initialized ...</span></pre>
<pre class="code">    twitTextPlaceholder = <span>CType</span>(implementationRoot.FindName(<span>&quot;twitStackPanelPlaceholder&quot;</span>), Canvas)

    <span>Dim</span> sp <span>As</span> <span>New</span> <span>C1StackPanel</span>()
    sp.IsHorizontal = <span>False
</span>    sp.ReplacePlaceHolder(twitTextPlaceholder, <span>True</span>)
    sp.AutoSize = AutoSize.Both
    sp.Padding = <span>New</span> Thickness(5, 5, 2, 5)
    sp.HorizontalAlignment = Alignment.Near
    sp.VerticalAlignment = Alignment.Near
    sp.ChildSpacing = <span>New</span> Size(2, 0)

    sp.Children.Add(twitMessage)
<span>End</span> <span>Sub</span>  </pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<p><strong>Control library</strong> (<em>TwitterSL.Common</em>): The custom control library contains just one object: TwitControl.&nbsp; An instance of this control is dynamically created for each Tweet returned from Twitter.&nbsp;&nbsp; The control is then inserted at runtime
 into the parent Tweet container.&nbsp; Take a look at the XAML of this control to see how some simple animation storyboards can be tied to each control and wired up to individual control events.</p>
<p><strong>Web project</strong> (<em>TwitterSLServer</em>): The web site project contains a single web page which hosts the Silverlight container.&nbsp; The project has been linked to the Silverlight project, and the default.htm and Page.xaml objects have been copied
 to the site.&nbsp; The web project is set as the startup project, but remember all of the &quot;work&quot; is done within the TwitterSL Silverlight project.</p>
<p><strong>Proxy web service</strong> (<em>TwitterWebService.asmx</em>):&nbsp; The local TwitterWebService .asmx is part of the TwitterSLServer web project.&nbsp; This is the proxy service used to contact the Twitter API directly.&nbsp; The web service allows for async behavior
 by providing each public method with a BeginXXX() and EndXXX() variant.&nbsp; The Silverlight project can call BeginXXX() and continue processing; the EndXXX() is invoked once the request is completed by Twitter and the proxy web service.</p>
<p><strong>Twitter API:</strong> Twitter provides a Representational State Transfer (RESTful) service to allow third-party applications to access the Twitter message exchanges.&nbsp; The API calls utilize HTTP Basic Authentication delivered via HTTP Requests to
 specified URLs, and returns back a list of messages in the desired format (XML, JSON, etc).&nbsp; The proxy web service delivers an XML snippet back to the Silverlight calling code for parsing and display.&nbsp; You can see how a request is created in the proxy web
 service methods below:</p>
<p><span>C#:</span></p>
<p>[<span>WebMethod</span>] <br>
<span>public</span> <span>string</span> GetArchive(<span>string</span> username, <span>
string</span> password) <br>
{ <br>
&nbsp;&nbsp;&nbsp; <span>try <br>
</span>&nbsp;&nbsp;&nbsp; { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>return</span> GetRequest(<span>string</span>.Format(<span>@&quot;http://twitter.com/statuses/user_timeline/{0}.xml&quot;</span>, username), username, password);
<br>
&nbsp;&nbsp;&nbsp; } <br>
&nbsp;&nbsp;&nbsp; <span>catch</span> (<span>Exception</span> ex) <br>
&nbsp;&nbsp;&nbsp; { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span>throw</span> ex; <br>
&nbsp;&nbsp;&nbsp; } <br>
}</p>
<p><span>private</span> <span>string</span> GetRequest(<span>string</span> uri, <span>
string</span> username, <span>string</span> password) <br>
{ <br>
&nbsp;&nbsp;&nbsp; <span>WebRequest</span> request = <span>HttpWebRequest</span>.Create(uri); <br>
</p>
<p>&nbsp;&nbsp;&nbsp; <span>if</span> (!<span>string</span>.IsNullOrEmpty(username) &amp;&amp; !<span>string</span>.IsNullOrEmpty(password))
<br>
&nbsp;&nbsp;&nbsp; { <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request.Credentials = <span>new</span> <span>NetworkCredential</span>(username, password);
<br>
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; <span>WebResponse</span> res = request.GetResponse(); <br>
&nbsp;&nbsp;&nbsp; <span>StreamReader</span> stream = <span>new</span> <span>StreamReader</span>(res.GetResponseStream());
<br>
&nbsp;&nbsp;&nbsp; <span>string</span> data = stream.ReadToEnd(); <br>
&nbsp;&nbsp;&nbsp; stream.Close(); <br>
&nbsp;&nbsp;&nbsp; <span>return</span> data; <br>
}</p>
<p><span>VB:</span></p>
<pre class="code">&lt;WebMethod()&gt; _
<span>Public</span> <span>Function</span> GetArchive(<span>ByVal</span> username <span>As</span> <span>String</span>, <span>ByVal</span> password <span>As</span> <span>String</span>) <span>As</span> <span>String
</span>    <span>Try
</span>        <span>Return</span> GetRequest(<span>String</span>.Format(<span>&quot;http://twitter.com/statuses/user_timeline/{0}.xml&quot;</span>, username), username, password)
    <span>Catch</span> ex <span>As</span> Exception
        <span>Throw</span> ex
    <span>End</span> <span>Try
</span><span>End</span> <span>Function</span></pre>
<pre class="code"><span>Private</span> <span>Function</span> GetRequest(<span>ByVal</span> uri <span>As</span> <span>String</span>, <span>ByVal</span> username <span>As</span> <span>String</span>, <span>ByVal</span> password <span>As</span> <span>String</span>) <span>As</span> <span>String
</span>    <span>Dim</span> request <span>As</span> WebRequest = HttpWebRequest.Create(uri)

    <span>If</span> <span>Not</span> <span>String</span>.IsNullOrEmpty(username) <span>AndAlso</span> <span>Not</span> <span>String</span>.IsNullOrEmpty(password) <span>Then
</span>        request.Credentials = <span>New</span> NetworkCredential(username, password)
    <span>End</span> <span>If

</span>    <span>Dim</span> res <span>As</span> WebResponse = request.GetResponse()
    <span>Dim</span> stream <span>As</span> StreamReader = <span>New</span> StreamReader(res.GetResponseStream())
    <span>Dim</span> data <span>As</span> <span>String</span> = stream.ReadToEnd()
    stream.Close()
    <span>Return</span> data
<span>End</span> <span>Function</span></pre>
<a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a>
<h3>Putting it together</h3>
<p>In the TwitterSL.Page class, the action kicks off when the user enters a Twitter username/password, and presses the &quot;Get&quot; button.&nbsp; The dropdown beside it determines which web request type will be issued.&nbsp; An AutoRefresh toggles, of course, the auto refreshing
 of the current message list.&nbsp; The line under &quot;AutoRefresh&quot; fades until the refresh occurs, one of the simple animations added to the XAML.</p>
<p><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/7883342/Toolbar1.jpg"></p>
<p>The Get button's click event trickles down to the GetWebRequest method, which calls the appropriate proxy web service method.&nbsp; Notice the call here using the &quot;Begin&quot; prefix, and passing a new AsyncCallback object to invoke the service asynchronously.&nbsp; The
 callback object specifies GetWebRequestResult as the target when the call finishes.</p>
<p><span>C#:</span></p>
<p>_twitterWebService.BeginGetTwits(username, password, <span>new</span> <span>AsyncCallback</span>(GetWebRequestResult),
<span>null</span>);</p>
<p><span>VB:</span></p>
<p><span>_twitterWebService.BeginGetTwits(username, password, <span>New</span> <span>
AsyncCallback</span>(<span>AddressOf</span> GetWebRequestResult), <span>Nothing</span>)</span></p>
<p><span></span>The web service simply sets up the appropriate url, builds an HTTP web request with authentication (if required), and issues the call (nothing too shocking here, but take a look at the code if you're not familiar with building up a web request).</p>
<p>Once the web service work is done, we're asynchronously delivered to the previously mentioned GetWebRequestResult method.&nbsp; This drops us into LoadTwits, which does the dirty work of parsing the returned XML snippet, creating new instances of the TwitControl
 for each message element and adding them to the parent container.</p>
<p><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/7883342/Control1.jpg"></p>
<p>It's here, however, where the simplistic beauty of RESTful interfaces show their harsh side: we're pretty dependent on their format, and this parsing code could easily break.&nbsp; Also, of course, the REST won't give us strong typing.&nbsp; Hey, this would be a good
 place for a wrapper project, a la the <a href="http://www.codeplex.com/FacebookToolkit" target="_blank">
Facebook Developer Toolkit</a>.&nbsp; And speaking of enhancements....</p>
<h3>Challenges to you</h3>
<p>The fun &amp; frustration of coding with new technology is overcoming the limitations of a limited feature set.&nbsp; The Twitterlight project is ripe for feature development in the coming months, as the Silverlight 2.0 Beta releases and control toolsets continue
 to emerge.&nbsp; Some challenges include:</p>
<ul>
<li>The TwitControl needs rich text support, to parse any urls into into clickable hyperlinks.&nbsp; Currently links show below the message as &quot;Follow Link&quot;
</li><li>Add more user credential security vs. current Basic Authentication </li><li>Incorporate new toolset and SIlverlight features as released </li></ul>
<h3>Bio</h3>
Steve Holstad is a software development consultant for <a href="http://www.claritycon.com" target="_blank">
Clarity Consulting</a>, based in Chicago, IL. Check out <a href="http://blogs.claritycon.com/blogs/steve_holstad/" target="_blank">
his blog</a> for other writings and contact information. <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Steve-Holstad/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3d2c8516cb40410c991c9e7600d04098">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Twitterlight-A-Silverlight-Twitter-client</comments>
      <itunes:summary>




Twitter, using simple SMS length messages, has changed how people stay connected.&amp;nbsp; Here&#39;s how to build a Silverlight web client to access the Twitter API and display your tweets in a layout of your choosing.&amp;nbsp; The Twitterlight
 code provides a solid starting point for communicating with any RESTful service interface, and you&#39;ll also see how to overcome Silverlight&#39;s cross-domain call limitations by leveraging a local proxy web service.



Steve Holstad
Steve&#39;s Blog

Difficulty: Intermediate
Time Required: 
Greater than 10 hours
Cost: Free
Software: Microsoft Visual Studio,

Silverlight 2.0 Alpha September Refresh, (NEW) 
Silverlight 2.0 Beta 1, 
ComponentOne Sapphire Toolset
Hardware: 





 
Developer Update (5/18/2009)
The Silverlight 2.0 RTW Source Code is available at the link below.&amp;nbsp; Please note that the RTW version contains no reference to the Sapphire controls used during the SL 2 Beta. 
Twitterlight_v22.zip 
I am planning to create a new Twitterlight version for Silverlight 3, so I&#39;m sad to say this code base won&#39;t be updated past 2.0.&amp;nbsp; Thanks for the feedback and support! 
Developer Update (4/1/2008)
Twitterlight has been updated to the newest Silverlight release: Silverlight 2.0 Beta 1.&amp;nbsp; You&#39;ll need this runtime installed in order to run the app at
twitterlight.com.&amp;nbsp; Don&#39;t forget that to compile the code, you must download, install and add references to the appropriate ComponentOne Sapphire control set. 
Introduction
I&#39;ve become a big believer in the power of Twitter to keep an informal social network of like-minded folks loosely yet immediately connected.&amp;nbsp; Often times developers have a decent number of contacts they&#39;d like to keep in contact with, but perhaps don&#39;t
 always have time to reach out one-on-one often enough.&amp;nbsp; Twitter provides a mechanism which somehow gives that constantly connected &amp;quot;feel&amp;quot;.&amp;nbsp; As a consultant that works at many sites, I wanted to create a web-based client to allow Twitte</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Twitterlight-A-Silverlight-Twitter-client</link>
      <pubDate>Sun, 24 Feb 2008 19:03:51 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Twitterlight-A-Silverlight-Twitter-client</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/7883342_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/7883342_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Steve Holstad</dc:creator>
      <itunes:author>Steve Holstad</itunes:author>
      <slash:comments>22</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Twitterlight-A-Silverlight-Twitter-client/RSS</wfw:commentRss>
    </item>
  <item>
      <title>YeahTrivia: Creating a Trivia Server/Client with WPF and WCF</title>
      <description><![CDATA[<span id="c4fmetadata">
<table class="" cellspacing="0" cellpadding="1" width="100%" border="0">
<tbody>
<tr class="entry_overview">
<td class="" width="50"><img height="50" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/yeahtriviathumb.gif" width="50"></td>
<td class=""><span class="entry_description">In this article I'll take you along for the ride as I attack the learning curve required to create a fun, interactive application using both the Microsoft Windows Presentation Foundation (WPF) and the Windows Communication
 Foundation (WCF). Afterwards, you'll have a flexible trivia client/server game ready to play by yourself or against friends, coworkers and your local know-it-all.&nbsp;
<em>And in honor of Halloween, I've included three games of horror movie trivia.</em></span></td>
</tr>
<tr>
<td class="" colspan="2">
<div class="entry_author">Steve Holstad</div>
<div class="entry_company"><a href="http://blogs.claritycon.com/blogs/steve_holstad/archive/2007/10/29/3403.aspx" target="_blank">The Bright Lights</a></div>
<br>
<div class="entry_details"><b>Difficulty: </b><span class="entry_details_input">Advanced</span></div>
<div class="entry_details"><b>Time Required:</b> <span class="entry_details_input">
6-10 hours</span></div>
<div class="entry_details"><b>Cost: </b><span class="entry_details_input">Free</span></div>
<div class="entry_details"><b>Software: </b><span class="entry_details_input">Visual Studio Express, 2005, 2008 Beta 2
<a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=10CC340B-F857-4A14-83F5-25634C3BF043&amp;displaylang=en">
Microsoft .NET Framework 3.0</a></span></div>
<div class="entry_details"><b>Hardware: </b><span class="entry_details_input"></span></div>
<div class="entry_details"><b>Download: </b><a class="" href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/YeahTrivia.zip" target="_blank">Download Source</a>
<ul>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</span>
<p>&nbsp;</p>
<h3>What can YeahTrivia do for me?</h3>
<p>Glad you asked. This project started when I decided I wanted to dive headfirst into learning WPF and WCF, without hacking through countless Hello World examples.&nbsp; And I wanted something fun that I could improve over time as my skills developed in these new
 technologies.&nbsp; In this article I'll take you along for the ride as I attack the learning curve required to create a fun, interactive application using both the Microsoft Windows Presentation Foundation (WPF) and the Windows Communication Foundation (WCF).
 Afterwards, you'll have a flexible trivia client/server game ready to play by yourself or against friends, coworkers and your local know-it-all.&nbsp; And in honor of Halloween, I've included three games of horror movie trivia.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/YeahTrivia_Client5.jpg"><img height="194" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/YeahTrivia_Client_thumb1.jpg" width="280" border="0"></a>
</p>
<p>In case you were wondering, the &quot;YeahTrivia&quot; name honors my new bride&nbsp;&amp; her&nbsp;favorite prefix.&nbsp; Think of it as&nbsp;YeeeeaaaaahhTrivia!</p>
<h3>Basic Setup</h3>
<p>This demo project was built using Visual Studio 2008 Beta 2, and is based on the Microsoft .NET Framework version 3.0.&nbsp; The game is fed by a small windows app that acts as a game server, providing game selection, user&nbsp;registration, question loading, response
 times, chat messaging&nbsp;and scorekeeping.&nbsp; The server loads a game by reading a predefined XML format, which we will look at a bit later.&nbsp; This dynamic load lets anyone create their own flavor of trivia game, with any number of questions.</p>
<p>The server app exposes one WCF endpoint, a wsDualHttpBinding channel that supports duplex (two-way) communication between the server and any number of game clients.&nbsp; Clients attach themselves to this endpoint and provide a callback address to the server.&nbsp;
 The server saves an instance of this callback channel and uses each client's instance to&nbsp;contact the clients en masse during general game flow.&nbsp; Enough talk, here's how to build one yourself.</p>
<h3>Trivia Common and WCF Service Interfaces</h3>
<p>The TriviaCommon project provides both the server and client projects access to shared objects.&nbsp; To keep things simple the Common project only contains two classes:</p>
<p>Constants.cs defines the AnswerItem enumeration, which gives easy access to the five answer options (None, A, B, C, D), and the QuestionItem struct.&nbsp; This structure is delivered to the client and contains question text, answer text, and the correct answer
 object of type AnswerItem.&nbsp; Notice that objects being directly passed over the wire need to be marked with the [DataContract] attribute.</p>
<p>The second class, Interfaces.cs is where our WCF fun begins.&nbsp; Take a look:</p>
<strong>C#:</strong><br>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.ServiceModel;
<span class="kwrd">using</span> System.Text;

<span class="kwrd">namespace</span> Trivia.Common
{
    <span class="preproc">#region</span> Interfaces

    <span class="preproc">#region</span> Service Interface

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Interface that defines Trivia service contract.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    [ServiceContract(CallbackContract = <span class="kwrd">typeof</span>(ITriviaCallback))]
    <span class="kwrd">public</span> <span class="kwrd">interface</span> ITrivia
    {
        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> RegisterUser(<span class="kwrd">string</span> userName);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> AcceptAnswer(<span class="kwrd">string</span> userName, <span class="kwrd">string</span> answerValue);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> ChatPublish(<span class="kwrd">string</span> userName, <span class="kwrd">string</span> message);
    }

    <span class="preproc">#endregion</span> Service Interface

    <span class="preproc">#region</span> Client Callback Interface

    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Interface that defines Trivia client callback contract.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">interface</span> ITriviaCallback
    {        
        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnGameStart(<span class="kwrd">int</span> questionCount);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnGameEnd();

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnUserRegistered(<span class="kwrd">string</span> userName);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnPublishChat(<span class="kwrd">string</span> userName, <span class="kwrd">string</span> chatMessage);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnQuestionLoad(<span class="kwrd">int</span> questionIndex, QuestionItem questionItem);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnQuestionEnd();

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnQuestionStatusUpdate(Int64 questionTimeRemaining);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnScoreboardUpdate(Dictionary&lt;<span class="kwrd">string</span>, Int64&gt; scoreboard);

        [OperationContract(IsOneWay = <span class="kwrd">true</span>)]
        <span class="kwrd">void</span> OnGameServerStopped();
    }

    <span class="preproc">#endregion</span> Client Callback Interface

    <span class="preproc">#endregion</span> Interfaces
}
</pre>
<pre class="csharpcode"></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>VB:</strong></p>
<pre class="csharpcode"><span class="kwrd">Imports</span> System
<span class="kwrd">Imports</span> System.Collections.Generic
<span class="kwrd">Imports</span> System.ServiceModel
<span class="kwrd">Imports</span> System.Text

<span class="kwrd">Namespace</span> Trivia.Common

<span class="preproc">#Region</span> <span class="str">&quot;Interfaces&quot;</span>

<span class="preproc">#Region</span> <span class="str">&quot;Service Interface&quot;</span>
    
    <span class="rem">''' &lt;summary&gt;</span>
    <span class="rem">''' Interface that defines Trivia service contract.</span>
    <span class="rem">''' &lt;/summary&gt;</span>
    &lt;ServiceContract(CallbackContract:=<span class="kwrd">GetType</span>(ITriviaCallback))&gt; _
    <span class="kwrd">Public</span> <span class="kwrd">Interface</span> ITrivia
        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> RegisterUser(<span class="kwrd">ByVal</span> userName <span class="kwrd">As</span> <span class="kwrd">String</span>)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> AcceptAnswer(<span class="kwrd">ByVal</span> userName <span class="kwrd">As</span> <span class="kwrd">String</span>, <span class="kwrd">ByVal</span> answerValue <span class="kwrd">As</span> <span class="kwrd">String</span>)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> ChatPublish(<span class="kwrd">ByVal</span> userName <span class="kwrd">As</span> <span class="kwrd">String</span>, <span class="kwrd">ByVal</span> message <span class="kwrd">As</span> <span class="kwrd">String</span>)
    <span class="kwrd">End</span> <span class="kwrd">Interface</span>
        
<span class="preproc">#End Region</span>

<span class="preproc">#Region</span> <span class="str">&quot;Client Callback Interface&quot;</span>

    <span class="rem">''' &lt;summary&gt;</span>
    <span class="rem">''' Interface that defines Trivia client callback contract.</span>
    <span class="rem">''' &lt;/summary&gt;</span>
    <span class="rem">''' &lt;remarks&gt;&lt;/remarks&gt;</span>
    <span class="kwrd">Public</span> <span class="kwrd">Interface</span> ITriviaCallback
        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
      <span class="kwrd">Sub</span> OnGameStart(<span class="kwrd">ByVal</span> questionCount <span class="kwrd">As</span> <span class="kwrd">Integer</span>)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnGameEnd()

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnUserRegistered(<span class="kwrd">ByVal</span> userName <span class="kwrd">As</span> <span class="kwrd">String</span>)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnPublishChat(<span class="kwrd">ByVal</span> userName <span class="kwrd">As</span> <span class="kwrd">String</span>, <span class="kwrd">ByVal</span> chatMessage <span class="kwrd">As</span> <span class="kwrd">String</span>)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnQuestionLoad(<span class="kwrd">ByVal</span> questionIndex <span class="kwrd">As</span> <span class="kwrd">Integer</span>, <span class="kwrd">ByVal</span> questionItem <span class="kwrd">As</span> QuestionItem)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnQuestionEnd()

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnQuestionStatusUpdate(<span class="kwrd">ByVal</span> questionTimeRemaining <span class="kwrd">As</span> <span class="kwrd">Long</span>)

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnScoreboardUpdate(<span class="kwrd">ByVal</span> scoreboard <span class="kwrd">As</span> Dictionary(Of <span class="kwrd">String</span>, <span class="kwrd">Long</span>))

        &lt;OperationContract(IsOneWay:=<span class="kwrd">True</span>)&gt; _
        <span class="kwrd">Sub</span> OnGameServerStopped()

    <span class="kwrd">End</span> <span class="kwrd">Interface</span>

<span class="preproc">#End Region</span>

<span class="preproc">#End Region</span>

<span class="kwrd">End</span> <span class="kwrd">Namespace</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>A few items of interest here.&nbsp; Notice we're importing the System.ServiceModel namespace.&nbsp; This is the key assembly when using WCF, so don't forget to add a reference to your project.&nbsp; The first interface, ITrivia, defines the operations the server is required
 to implement, which handle basic user actions: Register a team, accept an answer and accept a chat message.&nbsp; Easy.</p>
<p>The second interface, cleverly named ITriviaCallback, lays out the callback contract a client must fulfill in order to play nicely with our server.&nbsp; The operations listed here describe events the server will publish.&nbsp; These aren't actual events, but the
 naming convention &quot;OnX...&quot; helps you remember that these are server published activities.</p>
<p>Notice that the [OperationContract] attribute notifies WCF that each method is part of a service contract.&nbsp; The IsOneWay flag gives us &quot;fire-and-forget&quot; behavior (the app shouldn't wait around for a response).&nbsp; So now that the common objects are ready, let's
 move on to...</p>
<h3>Building the Trivia Server</h3>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/YeahTrivia_Server1.jpg"><img height="202" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/YeahTrivia_Server.jpg" width="240" border="0"></a>
</p>
<p>The YeahTrivia Server is a simple utility app, but don't let&nbsp;the plain looks fool you; I thought about calling this the BrainStumper Pumper, but this is a family site.&nbsp; This app&nbsp;lets a user (anyone acting as game admin)&nbsp;start the service, select the desired
 game, await team registrations, and then start the game.&nbsp; If this were to become a larger scale project, I would make this an IIS hosted service that manages multiple games and provides more autonomy.&nbsp; Until those sports bar royalty checks start rolling in,
 however, a utility app will do just fine.</p>
<p>The only form, GameServerDashboard, simply provides user interaction with the GameServer class.&nbsp; On startup, the form&nbsp;inits an instance of GameServer and tells it to start the service.&nbsp; It also loads all trivia question sets from the Games directory, and
 displays them in the list.</p>
<p>GameServer is the brain behind YeahTrivia.&nbsp;The attributes below set up the GameServer for action:</p>
<p><strong>C#:</strong><br>
</p>
<pre class="csharpcode">[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant
        ,InstanceContextMode = InstanceContextMode.Single)]
    <span class="kwrd">public</span> <span class="kwrd">class</span> GameServer : ITrivia</pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>&nbsp;</p>
<p><strong>VB:</strong><br>
</p>
<pre class="csharpcode">&lt;ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Reentrant, InstanceContextMode:=InstanceContextMode.<span class="kwrd">Single</span>)&gt; _
    <span class="kwrd">Public</span> <span class="kwrd">Class</span> GameServer
        <span class="kwrd">Implements</span> ITrivia</pre>
<pre class="csharpcode"></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>ConcurrencyMode.Reentrant prevents deadlocks between the&nbsp;apps&nbsp;by stating that while this service is single-threaded, callbacks are allowed to invoke&nbsp;new&nbsp;operations.</p>
<p>InstanceContextMode.Single sets the service as a singleton, so that all messages are delivered to the same object instance.</p>
<p>These are advanced topics if you're new to WCF, so I'll include some links at the end that helped clarify some of this for me.&nbsp; Let's keep moving forward by looking at a few activities of the game server:</p>
<p><em>Start the Service:</em>&nbsp; Passes in the configured base address as a Uri, inits and opens a new ServiceHost.</p>
<p><strong>C#:</strong></p>
<blockquote>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">void</span> StartService()
{
<span class="rem">   // Set base address and open service host</span>
   Uri baseAddress = <span class="kwrd">new</span> Uri(ConfigurationManager.AppSettings[CONFIG_KEY_BASEURI]);
   _serviceHost = <span class="kwrd">new</span> ServiceHost(<span class="kwrd">new</span> GameServer(), baseAddress);
   _serviceHost.Open();
}</pre>
</blockquote>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>VB:</strong></p>
<pre class="csharpcode">  <span class="kwrd">Public</span> <span class="kwrd">Sub</span> StartService()
     <span class="rem">'Set base address and open service host</span>
     <span class="kwrd">Dim</span> baseAddress <span class="kwrd">As</span> <span class="kwrd">New</span> Uri(ConfigurationManager.AppSettings(CONFIG_KEY_BASEURI))
     _serviceHost = <span class="kwrd">New</span> ServiceHost(<span class="kwrd">New</span> GameServer(), baseAddress)
     _serviceHost.Open()
  <span class="kwrd">End Sub</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><em></em>&nbsp;</p>
<p><em>Register a new team:</em>&nbsp;Saves off the callback, adds it to the callback collection and scoreboard containers, notifies the user of a successful registration, and notifies all game clients of the new team.</p>
<p><strong>C#:</strong></p>
<pre class="csharpcode"> <span class="kwrd">public</span> <span class="kwrd">void</span> RegisterUser(<span class="kwrd">string</span> userName)
 {
     _currentCallback = OperationContext.Current.GetCallbackChannel&lt;ITriviaCallback&gt;();

     <span class="rem">// Store callback</span>
     <span class="kwrd">if</span> (!_callbacks.ContainsKey(userName))
     {
         _callbacks.Add(userName, _currentCallback);
         _scoreboard.Add(userName, 0);
</pre>
<pre class="csharpcode">         <span class="rem">// Notify user of registration</span>
         _currentCallback.OnUserRegistered(userName);
</pre>
<pre class="csharpcode">         <span class="rem">// Notify clients of new user</span>
         <span class="kwrd">foreach</span> (<span class="kwrd">string</span> userKey <span class="kwrd">in</span> _callbacks.Keys)
         {
            _currentCallback = _callbacks[userKey];
            _currentCallback.OnPublishChat(GAME_USERKEY, <span class="kwrd">string</span>.Format(FORMAT_USER_REGISTERED, userName));
         }                
     }
     <span class="kwrd">else</span>
     {
         <span class="rem">// User already registered, throw exception</span>
         <span class="kwrd">throw</span> <span class="kwrd">new</span> Exception(ERROR_USER_ALREADY_EXISTS);
     }
 }</pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><strong>VB:</strong></p>
<pre class="csharpcode"><span class="kwrd">Public</span> <span class="kwrd">Sub</span> RegisterUser(<span class="kwrd">ByVal</span> userName <span class="kwrd">As</span> <span class="kwrd">String</span>) <span class="kwrd">Implements</span> ITrivia.RegisterUser
   _currentCallback = OperationContext.Current.GetCallbackChannel(Of ITriviaCallback)()

   <span class="rem">'Store callback</span>
   <span class="kwrd">If</span> <span class="kwrd">Not</span> _callbacks.ContainsKey(userName) <span class="kwrd">Then</span>
      _callbacks.Add(userName, _currentCallback)
      _scoreboard.Add(userName, 0)

      <span class="rem">'Notify user of registration</span>
      _currentCallback.OnUserRegistered(userName)

      <span class="rem">'Notify clients of new user</span>
      <span class="kwrd">For</span> <span class="kwrd">Each</span> userKey <span class="kwrd">As</span> <span class="kwrd">String</span> <span class="kwrd">In</span> _callbacks.Keys
         _currentCallback = _callbacks(userKey)
         _currentCallback.OnPublishChat(GAME_USERKEY, <span class="kwrd">String</span>.Format(FORMAT_USER_REGISTERED, userName))
      <span class="kwrd">Next</span>
   <span class="kwrd">Else</span>
      <span class="rem">'User already registered, throw exception</span>
      <span class="kwrd">Throw</span> <span class="kwrd">New</span> Exception(ERROR_USER_ALREADY_EXISTS)
   <span class="kwrd">End</span> <span class="kwrd">If</span>
<span class="kwrd">End Sub</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style><style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>You can start to see how the server is able to handle incoming calls and process them back to the clients using the duplex channel.&nbsp; I'll leave the rest of the server actions for you to examine on your own.</p>
<h3>Building the Game Client (WCF) </h3>
<p>Address, Binding, Contract.&nbsp; These are the ABC's of WCF.&nbsp; The client's app.config file handles connecting to the service and specifying the channel and contract used to interact with it.&nbsp; Examine the client portion of the client .config:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">client</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">endpoint</span> <span class="attr">address</span><span class="kwrd">=&quot;http://localhost:8088/Trivia&quot;</span> <span class="attr">binding</span><span class="kwrd">=&quot;wsDualHttpBinding&quot;</span>
      <span class="attr">bindingConfiguration</span><span class="kwrd">=&quot;WSDualHttpBinding_ITrivia&quot;</span> <span class="attr">contract</span><span class="kwrd">=&quot;Trivia.Common.ITrivia&quot;</span>
      <span class="attr">name</span><span class="kwrd">=&quot;WSDualHttpBinding_ITrivia&quot;</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;/</span><span class="html">endpoint</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">client</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>The address points to the exposed service endpoint.&nbsp; The binding sets the channel as &quot;wsDualHttpBinding&quot; (our http duplex channel).&nbsp; The bindingConfiguration attribute is an optional&nbsp;pointer to another group of configurations for the binding, and finally,
 the contract sets the interface with which our client will be interacting.</p>
<p>Next it's time to generate a proxy class.&nbsp;&nbsp;Memorize this: Svcutil.exe is your friend.&nbsp; The client needs a proxy class that it can use to interact with the service model.&nbsp; The&nbsp;utility is a bit tricky at first, because of the wealth of optional flags, but
 stick with it, it's better than coding the proxy class by hand!&nbsp; You can generate your client code by starting the service and running a command line similar to this:</p>
<pre class="csharpcode">svcutil /language:cs /out:ServerProxy.cs <a href="http://localhost:8088/Trivia">http://localhost:8088/Trivia</a></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Add the generated class to the client project and you can begin to interact with the service.&nbsp; The svcutil is available as part of the Windows SDK.&nbsp; Check out the referenced site below&nbsp;for more information on this handy utility.</p>
<h3>Building the Game Client (WPF)</h3>
<p>Building the WPF portion of the client app was really a learning experience, and it will&nbsp;be the&nbsp;priority for me to improve in a later version.&nbsp; Learning to program in XAML markup can seem daunting, and it requires a large paradigm shift on your part in order
 to grasp the new concepts.&nbsp;&nbsp;Microsoft Expression is powerful tool for XAML work, but this time I coded all of the XAML by hand in order to fully see what was taking place inside.</p>
<p>A deep discussion of WPF is beyond the scope of this article, but take a look at the example code to get an idea of the layout.&nbsp; An excellent book to start with is
<u>WPF Unleashed</u> by Adam Nathan.&nbsp; An easy read (for a programming book), and solid examples to get you rolling.</p>
<p>I've set up the client using&nbsp;a instance of the Window class, which is shown below:</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Window</span> <span class="attr">x:Class</span><span class="kwrd">=&quot;Trivia.Client.GameClient&quot;</span>
    <span class="attr">xmlns</span><span class="kwrd">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;</span>
    <span class="attr">xmlns:x</span><span class="kwrd">=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;</span>
    <span class="attr">Title</span><span class="kwrd">=&quot;YeahTrivia&quot;</span> <span class="attr">MinHeight</span><span class="kwrd">=&quot;620&quot;</span> <span class="attr">MinWidth</span><span class="kwrd">=&quot;620&quot;</span> 
    <span class="attr">WindowStartupLocation</span><span class="kwrd">=&quot;CenterScreen&quot;</span> <span class="attr">WindowState</span><span class="kwrd">=&quot;Normal&quot;</span>  <span class="attr">Style</span><span class="kwrd">=&quot;{DynamicResource MainWindowStyle}&quot;</span>
    <span class="attr">Background</span><span class="kwrd">=&quot;{DynamicResource MainWindowBackgroundBrush}&quot;</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>The window class sets up the outermost container of the app, and includes two default namespaces.&nbsp; I've also set a few other properties here: a min height and width, window startup location &amp; state, and two styling attributes set by dynamic resources.</p>
<p>Resources are a great way to further separate form &amp; function, allowing a programmer to handle the behavior of an app, while a designer can work simultaneously on the look, all without stepping on too many toes.&nbsp; As a 2.0 task for this project, I would remove
 all inline styling and move them into resource dictionaries.&nbsp; A dictionary contains styles and control templates (a skin) that can be loaded &amp; switched&nbsp;at runtime.</p>
<p>ResourceDictionaries are linked to your XAML in the App.Xaml file.&nbsp; Once you've set up the reference, the&nbsp;example above show&nbsp;how to&nbsp;reference the current dictionary:&nbsp; The Background and Style&nbsp;properties are set as dynamic resources by naming&nbsp;the Keys specified
 in the&nbsp;ResourceDictionary (DefaultResources.xaml):</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">LinearGradientBrush</span> <span class="attr">x:Key</span><span class="kwrd">=&quot;MainWindowBackgroundBrush&quot;</span> <span class="attr">StartPoint</span><span class="kwrd">=&quot;.45,.45&quot;</span> <span class="attr">EndPoint</span><span class="kwrd">=&quot;.55,.55&quot;</span> <span class="attr">SpreadMethod</span><span class="kwrd">=&quot;Reflect&quot;</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">GradientStop</span> <span class="attr">Offset</span><span class="kwrd">=&quot;0&quot;</span> <span class="attr">Color</span><span class="kwrd">=&quot;DodgerBlue&quot;</span><span class="kwrd">/&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">GradientStop</span> <span class="attr">Offset</span><span class="kwrd">=&quot;.8&quot;</span> <span class="attr">Color</span><span class="kwrd">=&quot;DarkSlateBlue&quot;</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">LinearGradientBrush</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;</span><span class="html">Style</span> <span class="attr">TargetType</span><span class="kwrd">=&quot;{x:Type Window}&quot;</span> <span class="attr">x:Key</span><span class="kwrd">=&quot;MainWindowStyle&quot;</span><span class="kwrd">&gt;</span>
   <span class="kwrd">&lt;</span><span class="html">Setter</span> <span class="attr">Property</span><span class="kwrd">=&quot;FontFamily&quot;</span> <span class="attr">Value</span><span class="kwrd">=&quot;Trebuchet MS&quot;</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">Style</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Not quite as easy as CSS, but for a Forms project, it's a nice feature.&nbsp; The sample ResourceDictionary includes a button control template for all of my buttons, based on Rob Eisenberg's excellent article (link below).</p>
<p>One other interesting feature to point out: Take a look at the code-behind class MarshalToUIThread method, which accepts a SendOrPostCallback parameter.&nbsp; This is where&nbsp;the client is transferring actions from the sync thread back to the UI thread.&nbsp; In each
 interface method implementation (OnX..), you can see how I wrap any UI-directed code and assign&nbsp;it to the postCallback field.&nbsp; Passing this to the MarshalToUIThread method simply issues a SynchronizationContext.Post call, and the UI thread executes as expected.</p>
<h3>Creating a New Trivia Game (XML)</h3>
<p>New trivia games can be added at any time using&nbsp;the simple XML format shown here.&nbsp; After installing the server application, simply drop the new .XML file into the Games directory ([Server Install Location]\Yeah Trivia Server\Games).&nbsp; This demo comes pre-loaded
 with Geek Trivia, and&nbsp;a special Halloween Trivia version in case you're feeling festive.</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">TriviaQuestionDataSet</span> <span class="attr">xmlns</span><span class="kwrd">=&quot;http://tempuri.org/TriviaQuestionDataSet.xsd&quot;</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">TriviaQuestion</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">QuestionText</span><span class="kwrd">&gt;</span>Name the highest grossing Monty Python creation.<span class="kwrd">&lt;/</span><span class="html">QuestionText</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextA</span><span class="kwrd">&gt;</span>A) Holy Grail<span class="kwrd">&lt;/</span><span class="html">AnswerTextA</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextB</span><span class="kwrd">&gt;</span>B) The Life of Brian<span class="kwrd">&lt;/</span><span class="html">AnswerTextB</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextC</span><span class="kwrd">&gt;</span>C) Shrubbery<span class="kwrd">&lt;/</span><span class="html">AnswerTextC</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextD</span><span class="kwrd">&gt;</span>D) The Meaning of Life<span class="kwrd">&lt;/</span><span class="html">AnswerTextD</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">CorrectAnswerKey</span><span class="kwrd">&gt;</span>A<span class="kwrd">&lt;/</span><span class="html">CorrectAnswerKey</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">TriviaQuestion</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">TriviaQuestion</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">QuestionText</span><span class="kwrd">&gt;</span>Ferris Bueller's best friend was _________.<span class="kwrd">&lt;/</span><span class="html">QuestionText</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextA</span><span class="kwrd">&gt;</span>A) Sloane Peterson<span class="kwrd">&lt;/</span><span class="html">AnswerTextA</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextB</span><span class="kwrd">&gt;</span>B) Edward R. Rooney<span class="kwrd">&lt;/</span><span class="html">AnswerTextB</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextC</span><span class="kwrd">&gt;</span>C) Charlie Sheen<span class="kwrd">&lt;/</span><span class="html">AnswerTextC</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">AnswerTextD</span><span class="kwrd">&gt;</span>D) Cameron Frye<span class="kwrd">&lt;/</span><span class="html">AnswerTextD</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">CorrectAnswerKey</span><span class="kwrd">&gt;</span>D<span class="kwrd">&lt;/</span><span class="html">CorrectAnswerKey</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">TriviaQuestion</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">TriviaQuestionDataSet</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style><style type="text/css">
<!--
.csharpcode
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{margin:0em;
	width:100%;
	background-color:#f4f4f4}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<h3>It's Time to Play YeahTrivia</h3>
<p>Install both the Server and Client applications.&nbsp; First, fire up the server, and then start your game client(s).&nbsp; Once everyone has registered a team, select your game and hit &quot;Start Game&quot;.&nbsp;&nbsp;&nbsp; You're off...</p>
<h3>Game Over</h3>
<p>So there you have it.&nbsp; We've seen&nbsp;how WCF manages communication between objects, extracting complicated service protocols away from your code.&nbsp; And just a&nbsp;small subset of the WPF functionality has shown us&nbsp;how quickly a rich, XAML-based UI can come together.&nbsp;
 And maybe, just maybe, you've learned why a CD is 74 minutes long... but I'm not telling.</p>
<p>I challenge you to improve on this initial version of YeahTrivia:&nbsp; Crack open the XAML and add animations, images, video, music &amp; more.&nbsp;&nbsp;Create a self-maintaining server to run multiple games at once.&nbsp; Add a High Score storage system.&nbsp; Extend the WCF settings
 to enable other communication channels.&nbsp; Add a new skin.&nbsp;Create new question files to share with us.&nbsp;&nbsp;Whatever you do, have fun and&nbsp;go nuts.&nbsp; YeahCoding4Fun.</p>
<p>Download <a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/5773166/YeahTrivia.zip">
source files</a></p>
<p>Download <a href="http://employees.claritycon.com/sholstad/blog/Coding4Fun/YeahTrivia/">
compiled demo (C# and VB)</a></p>
<h3>About The Author</h3>
<p>Steve Holstad works as a software consultant for Clarity Consulting in Chicago.&nbsp; He blogs at
<a href="http://blogs.claritycon.com/blogs/steve_holstad/default.aspx" target="_blank">
The Bright Lights</a>, and is available via email at <a href="mailto:sholstad@claritycon.com">
sholstad@claritycon.com</a></p>
<p>&nbsp;</p>
<h3>References</h3>
<p><a href="http://wcf.netfx3.com/" target="_blank">wcf.netfx3.com/</a><br>
<a href="http://wpf.netfx3.com/" target="_blank">wpf.netfx3.com/</a><br>
<a href="http://msdn2.microsoft.com/en-us/library/ms733133.aspx" target="_blank">Generating a client proxy class</a><br>
<a href="http://msdn2.microsoft.com/en-us/library/system.servicemodel.concurrencymode.aspx" target="_blank">ConcurrencyMode</a><br>
<a href="http://msdn2.microsoft.com/en-us/library/ms733133.aspx">SvcUtil.exe Tutorial</a>
<br>
<a href="http://devlicio.us/blogs/rob_eisenberg/archive/2006/12/03/net-3-0-crash-course-part-6-wpf-styles-and-control-templates.aspx" target="_blank">Rob Eisenberg's WPF control template</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><em>Special thanks to <a href="https://blogs.claritycon.com/blogs/bryan_dougherty/default.aspx" target="_blank">
Bryan Dougherty</a> for the WCF jumpstart, <a href="https://blogs.claritycon.com/blogs/kevin_marshall/default.aspx" target="_blank">
Kevin Marshall</a> for the Halloween Trivia and <a href="http://blogs.techrepublic.com.com/geekend/index.php?cat=400&amp;submit=view" target="_blank">
Jay Garmon</a>, creator of TechRepublic's Geek Trivia.</em></p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Steve-Holstad/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:85a5cfe91af449478d329e7600d1c0ef">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/YeahTrivia-Creating-a-Trivia-ServerClient-with-WPF-and-WCF</comments>
      <itunes:summary>




In this article I&#39;ll take you along for the ride as I attack the learning curve required to create a fun, interactive application using both the Microsoft Windows Presentation Foundation (WPF) and the Windows Communication
 Foundation (WCF). Afterwards, you&#39;ll have a flexible trivia client/server game ready to play by yourself or against friends, coworkers and your local know-it-all.&amp;nbsp;
And in honor of Halloween, I&#39;ve included three games of horror movie trivia.



Steve Holstad
The Bright Lights

Difficulty: Advanced
Time Required: 
6-10 hours
Cost: Free
Software: Visual Studio Express, 2005, 2008 Beta 2

Microsoft .NET Framework 3.0
Hardware: 
Download: Download Source








&amp;nbsp; 
What can YeahTrivia do for me?
Glad you asked. This project started when I decided I wanted to dive headfirst into learning WPF and WCF, without hacking through countless Hello World examples.&amp;nbsp; And I wanted something fun that I could improve over time as my skills developed in these new
 technologies.&amp;nbsp; In this article I&#39;ll take you along for the ride as I attack the learning curve required to create a fun, interactive application using both the Microsoft Windows Presentation Foundation (WPF) and the Windows Communication Foundation (WCF).
 Afterwards, you&#39;ll have a flexible trivia client/server game ready to play by yourself or against friends, coworkers and your local know-it-all.&amp;nbsp; And in honor of Halloween, I&#39;ve included three games of horror movie trivia. 

 
In case you were wondering, the &amp;quot;YeahTrivia&amp;quot; name honors my new bride&amp;nbsp;&amp;amp; her&amp;nbsp;favorite prefix.&amp;nbsp; Think of it as&amp;nbsp;YeeeeaaaaahhTrivia! 
Basic Setup
This demo project was built using Visual Studio 2008 Beta 2, and is based on the Microsoft .NET Framework version 3.0.&amp;nbsp; The game is fed by a small windows app that acts as a game server, providing game selection, user&amp;nbsp;registration, question loading, response
 times, chat messaging&amp;nbsp;and scorekeeping.&amp;nbsp; The server </itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/YeahTrivia-Creating-a-Trivia-ServerClient-with-WPF-and-WCF</link>
      <pubDate>Mon, 29 Oct 2007 21:01:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/YeahTrivia-Creating-a-Trivia-ServerClient-with-WPF-and-WCF</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/5773166_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/5773166_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Steve Holstad</dc:creator>
      <itunes:author>Steve Holstad</itunes:author>
      <slash:comments>12</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/YeahTrivia-Creating-a-Trivia-ServerClient-with-WPF-and-WCF/RSS</wfw:commentRss>
      <category>Gaming</category>
      <category>Halloween</category>
      <category>Windows</category>
      <category>arcade</category>
      <category>windows miscellaneous</category>
      <category>card and board games</category>
    </item>    
</channel>
</rss>