<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-8134680341505762758</atom:id><lastBuildDate>Sun, 31 Jul 2011 06:33:32 +0000</lastBuildDate><category>c#</category><category>t-sql</category><category>performance tuning</category><category>tcp/ip</category><category>flash</category><category>javascript</category><category>schema design</category><category>debugging</category><category>reporting services</category><category>silverlight</category><category>wpf</category><category>html</category><category>vs2008</category><category>source code</category><category>microsoft</category><category>.net</category><category>app design</category><category>web server</category><category>tutor.com classroom</category><category>conferences</category><category>sql server</category><category>vista</category><title>Russell Greenspan's Notes on Software Development</title><description>&lt;a href="http://www.russellgreenspan.com"&gt;Russell Greenspan's&lt;/a&gt; Notes on Software Development</description><link>http://russellgreenspan.blogspot.com/</link><managingEditor>noreply@blogger.com (raulgspan)</managingEditor><generator>Blogger</generator><openSearch:totalResults>68</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/russellgreenspan" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="russellgreenspan" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-6160447612359442288</guid><pubDate>Thu, 31 Dec 2009 16:14:00 +0000</pubDate><atom:updated>2009-12-31T11:28:58.844-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">reporting services</category><title>Matrix reports in Reporting Services 2005</title><description>Matrix reports are extremely useful when you have data organized in rows that you want to transpose to columns (similar to creating a Pivot Table in Excel). Here’s an example of how to use a Matrix report and how to hack your way through some additional features you’re likely to need.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Matrix&lt;/b&gt;&lt;br /&gt;Say you have a dataset of user transactions, with {Username, TransactionDate, Amount}. Instead of seeing this information as a long table, you want to see one row per user, with the total amount spent per day in columns. This would let you quickly compare who spent what by day.&lt;br /&gt;&lt;br /&gt;Doing this as a Matrix report is easy. Select “Add New Report” from Visual Studio 2005, enter your query or sproc, and pick ‘Matrix’ report type. The next page is where all the magic happens; using our example, put {Username} into ‘Rows’, {TransactionDate} into ‘Columns’, and {Adjustment} into ‘Details’. Click ‘Finish’, and you’ll see that Visual Studio has created the table, assuming you wanted to SUM the Amount for each user. In this case that is exactly what we want, but if we needed a different aggregate operation we’d just edit the details Textbox and change ‘Sum()’ as desired.&lt;br /&gt;&lt;br /&gt;The first thing you’ll notice when you preview the report is that this isn’t exactly what we want, since the TransactionDate column is using the full DateTime value, which creates a column for each distinct DateTime. Instead we just want a single column per unique day. So let’s add a calculated field by going to the ‘Data’ tab, clicking the ‘…’ button, and adding a new calculated field TransactionDateFormatted with value &lt;span style=";font-family:courier new;font-size:100%;"  &gt;=Format(Fields!TransactionDate.Value, "g")&lt;/span&gt;. We then have to change the report to use this new field in two places:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;In In the textbox displaying the date. Right-click on the column header textbox and change the Value from &lt;span style="font-family:courier new;"&gt;=Fields!TransactionDateFormatted.Value&lt;/span&gt; to &lt;span style="font-family:courier new;"&gt;=Fields!TransactionDateFormatted.Value&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;In the grouping definition. Right-click on the table, select ‘Properties’, go to the ‘Groups’ tab, edit the column grouping definition that was automatically created, and change the expression to &lt;span style="font-family:courier new;"&gt;=Fields!TransactionDateFormatted.Value&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Viola! All is good.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Unplug from the Matrix&lt;/b&gt;&lt;br /&gt;Well, almost. And here’s the part you’ve been waiting for, where we take off the gloves, agree that Reporting Services 2005 does do lots of things well, and that for what it is, we like it. Thing is, sometimes to get the job done you have to get a little dirty.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Additional Columns&lt;/b&gt;&lt;br /&gt;Let’s say we have the same dataset, but this time we also have UserId, and we want to show both the Username and the UserId in each row. Sounds straightforward enough. But you’ll notice that this isn’t so simple, since you can’t add a ‘Column’, only a ‘ColumnGroup’, which would add a column for each unique UserId (the exact opposite of what we want). You have to tilt your head to the side a bit and think like the Matrix (report). What we want here is actually another ‘RowGroup’, since the UserId value will appear in a row, but we want to group by a constant value so as not to create a second group for each user. So right-click on the table, choose ‘Add Row Group’, and enter &lt;span style="font-family: courier new;"&gt;=1&lt;/span&gt; as the grouping expression. Then on the report, change the newly created Textbox’s value from &lt;span style="font-family: courier new;"&gt;=1&lt;/span&gt; to &lt;span style="font-family: courier new;"&gt;=Fields!UserId.Value&lt;/span&gt;. Taking a look in Preview mode, we see that we now have Username and UserId in each row, and we’re happy.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Column Headers&lt;/b&gt;&lt;br /&gt;Kind of. What we really need now is a column header for each of these columns, since it’s a bit unclear what’s what. So we return the Layout tab and go to edit the value of the column header Textbox… but alas! There’s only one, merged Textbox for the two columns. You’ll see that if you add additional RowGroups using the same technique there is still just a single, merged Textbox for the entire span of the column header.&lt;br /&gt;&lt;br /&gt;Time to bust out the heavy guns. Open the Toolbox and drag a Rectangle into that single, merged Textbox. You’ll see the dots in the background of the report now. Then drag two Textboxes onto the Rectangle, and position them so that one is above the first column (Username) and the other is above the second column (UserId). Adjust the widths of the Textboxes so that they exactly match the widths of the RowGroups, edit the Textboxes’ values to be “Username” and “UserId”, and go back to preview mode. Now we’re cooking.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Enter Chris Hays&lt;/b&gt;&lt;br /&gt;Almost. Now what we say is “What’d be really great here is zebra-striping”, so that we can easily see each row. But you’ll notice that the traditional technique of zebra-striping a reporting services report (setting the background color to &lt;span style="font-family: courier new;"&gt;=iif(RunningValue(Fields!UserId.Value,CountDistinct, Nothing) Mod 2, "WhiteSmoke", "Ivory")&lt;/span&gt;) just doesn’t work. This time tilt your head to the other side, and keep tilting. For this hack we turn to Chris Hays and his Reporting Services Sleazy Hacks Weblog, which is far and away the best (only?) source of “How-Do-I”’s on Reporting Services 2005. The blog is from 2004-2006, but it’s relevance hasn’t changed. Read through everything he’s written.&lt;br /&gt;&lt;br /&gt;Conveniently, Chris has a Green Bar Matrix posting that will step us through this (yes, it’s going to get real ugly). Following his instructions:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Add another RowGroup (at the innermost position, after the UserId RowGroup we added) with a constant (&lt;span style="font-family: courier new;"&gt;=1&lt;/span&gt;) grouping expression. Change the name of the newly created RowGroup’s TextBox to "&lt;span style="font-family: courier new;"&gt;ColorNameTextbox&lt;/span&gt;".&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Put the background color calculation (&lt;span style="font-family: courier new;"&gt;=iif(RunningValue(Cstr(Fields!UserId.Value), CountDistinct, Nothing) Mod 2, "WhiteSmoke", "Ivory")&lt;/span&gt;) into the Value property of ColorNameTextbox.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Set the BackgroundColor property of this entire new RowGroup to &lt;span style="font-family: courier new;"&gt;=Value&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Set the BackgroundColor property of the matrix data cell Textbox (the one that does the Sum()) to &lt;span style="font-family: courier new;"&gt;=ReportItems!ColorNameTextbox.Value&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Set the BackgroundColor property of the other RowGroups (for UserId and Username) to the same grouping expression that we used for the Value of ColorNameTextbox (&lt;span style="font-family: courier new;"&gt;=iif(RunningValue(Cstr(Fields!UserId.Value), CountDistinct, Nothing) Mod 2, "WhiteSmoke", "Ivory")&lt;/span&gt;).&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hide the newly created RowGroup by setting the FontColor to &lt;span style="font-family: courier new;"&gt;=Value&lt;/span&gt;, the FontSize to 1pt, and the Size to Width of 0px. You can also hide the borders as Chris suggests if you mind them.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;b&gt;Go Wash Your Hands&lt;/b&gt;&lt;br /&gt;Phew! We now have exactly what we wanted, and we only had to feel a little bit dirty about getting it. It’s not deal-with-the-devil kind of stuff, but still, it’s pretty nasty.&lt;br /&gt;&lt;br /&gt;But that’s OK. We love Reporting Services. Come back to reality (if you remember what that is) and plug back into the Matrix. Life is good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-6160447612359442288?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/12/matrix-reports-in-reporting-services.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-5876911293083531195</guid><pubDate>Tue, 01 Dec 2009 22:25:00 +0000</pubDate><atom:updated>2009-12-01T17:29:47.720-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">flash</category><title>Microphone Access in Silverlight App: LIVE</title><description>Just a heads up that the technique described earlier (&lt;a href="http://russellgreenspan.blogspot.com/2009/01/microphone-access-in-silverlight-via.html"&gt;using Flash and Javascript for microphone support in a Silverlight app&lt;/a&gt;) is live now in &lt;a href="http://www.tutor.com/Classroom/Classroom.aspx?Practice=1"&gt;the Tutor.com Classroom&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;You'll need to create an account and connect to a tutor to see it in action (click the 'Connect to a Tutor' button in the classroom to get started)--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-5876911293083531195?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/12/microphone-access-in-silverlight-app.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-4051787354626132543</guid><pubDate>Mon, 04 May 2009 20:57:00 +0000</pubDate><atom:updated>2009-05-14T13:48:04.301-04:00</atom:updated><title>don't save foreign key relationships for "the end"</title><description>consider adding foreign keys part of creating a table; if you haven't set up foreign key relationships, you haven't finished creating your table.&lt;p&gt;indexes, on the other hand, can be saved for "the end", once you get a better sense of how you're querying the tables and what's most optimal. but even with indexes, if you have a good sense when you're creating the table of how you're most likely to access the data, you're better off taking an educated guess early than never doing it late--&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-4051787354626132543?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/05/dont-save-foreign-key-relationships-for.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-8593765883641462962</guid><pubDate>Fri, 10 Apr 2009 02:01:00 +0000</pubDate><atom:updated>2009-04-09T22:03:12.710-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">sql server</category><title>using SQL Profiler to monitor database calls</title><description>just in case anyone’s not familiar with SQL Profiler: this is the app that gives you low-level database monitoring so you can trace all database calls. you can customize what you monitor to get a variety of information.&lt;br /&gt;&lt;br /&gt;so for example, if you want to set up a trace to see all database calls from your web server, launch Profiler, click the New Trace… button, connect locally, and go to the second tab:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;check checkboxes in the DatabaseName column&lt;/li&gt;&lt;li&gt;click the Column Filters… button and add filters for:&lt;br /&gt;o DatabaseName Like =&gt; your database&lt;br /&gt;o NTUserName Like =&gt; nt identity you run your webserver as&lt;br /&gt;o TextData Like =&gt; exec&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-8593765883641462962?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/04/using-sql-profiler-to-monitor-database.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-7706860860041434091</guid><pubDate>Thu, 26 Feb 2009 16:56:00 +0000</pubDate><atom:updated>2009-02-26T12:12:18.648-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">reporting services</category><title>use format codes in report files</title><description>the best way to format datetime/number values in an RDL file is with the textbox’s Format property. you use the same format codes that you use in .NET and elsewhere, and you don’t have to worry about null values (null’s appear as empty strings). for example, common date format codes are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;d&lt;/span&gt; – 2/26/2009&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;D&lt;/span&gt; – Thursday, February 26, 2009&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;g&lt;/span&gt; – 2/26/2009 11:52am&lt;br /&gt;&lt;br /&gt;some number/currency codes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;g&lt;/span&gt; – 1234&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;N&lt;/span&gt; – 1,234.00&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;C&lt;/span&gt; – $1234.12&lt;br /&gt;&lt;br /&gt;if you forget the codes, you can get the VS2005 to show you them by right-clicking on the textbox and choosing ‘Properties’, going to the ‘Format’ tab, and clicking the ‘…’ button next to ‘Format code’.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-7706860860041434091?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/02/use-format-codes-in-report-files.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-926871800139639959</guid><pubDate>Tue, 03 Feb 2009 19:18:00 +0000</pubDate><atom:updated>2009-02-26T12:12:42.098-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">vs2008</category><category domain="http://www.blogger.com/atom/ns#">sql server</category><category domain="http://www.blogger.com/atom/ns#">reporting services</category><title>report server rdl files in visual studio 2008</title><description>hacked my way through this mostly by accident; if you rename a .rdl file to .rdlc, then you can open the file in visual studio 2008 and use the same GUI for report file edits that you have in 2005. you don’t get the data and preview tabs, so you need to make data source edits manually in notepad, but if you find yourself with only vs 2008 and need to make .rdl edits, this is a good way to get some GUI help--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-926871800139639959?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/02/report-server-rdl-files-in-visual.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-529620945685945286</guid><pubDate>Thu, 22 Jan 2009 15:34:00 +0000</pubDate><atom:updated>2009-01-22T17:44:57.298-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">flash</category><title>Microphone access in Silverlight via Flash and JavaScript</title><description>Silverlight is unquestionably a powerful tool for .NET application developers; using almost of all the same WPF skills,.NET developers can create rich internet applications (RIA) right out of the gate. However, Silverlight has no microphone/webcam support, and if you need this functionality in a cross-browser RIA, the common thinking is cross out Silverlight and pencil in Flash or Java.&lt;br /&gt;&lt;br /&gt;While it's true that you'll need to dip into Flash or Java for microphone/webcam support (at least until Silverlight 3, and &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/11/16/update-on-silverlight-2-and-a-glimpse-of-silverlight-3.aspx" target="_blank"&gt;possibly not even then&lt;/a&gt;), there's no reason you can't take advantage of Silverlight as your base application host and selectively use Flash as necessary for Silverlight's missing features. Then, using a JavaScript bridge, you can get these browser technologies communicating with each other fairly painlessly. This integrated solution is what we're considering at Tutor.com when we add voice communication support to &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;the Tutor.com Classroom&lt;/a&gt;, and this post will detail how to use Flash for microphone support inside a Silverlight application, where the button controlling the microphone on/off switch is in the Silverlight application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Flash: Microphone management&lt;/b&gt;&lt;br /&gt;First, we'll create a simple Flash movie (I'm using ActionScript 2) that manages and outputs microphone input. Thankfully, there's really very little code you need to write to do this; just note that your Flash movie must be at least 250x150 to allow room for the microphone Allow/Decline dialog, and if you don't want the movie to be visible, you need to set its background color to transparent. &lt;br /&gt;&lt;br /&gt;As an aside, note that there's similarly very little code you need to write to connect to a Flash Media Server (FMS) for real-time communication, although the example here omits the FMS part. As another aside, note that the code for Flash webcam support is almost identical, except instead of a Microphone object you're working with a Camera object.&lt;br /&gt;&lt;br /&gt;OK, so in the first frame of your Flash movie, write a function to access the microphone and monitor microphone activity:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;var mic:Microphone = null;&lt;br /&gt;&lt;br /&gt;function toggleVoice(isOn:Boolean)&lt;br /&gt;{&lt;br /&gt;  //setup the mic&lt;br /&gt;  if (mic == null)&lt;br /&gt;  {  &lt;br /&gt;    //call Microphone.get() to access the microphone and prompt user with Allow/Decline dialog&lt;br /&gt;    mic = Microphone.get();&lt;br /&gt;&lt;br /&gt;    //Microphone.get() will return null if user declined access&lt;br /&gt;    if (mic == null)&lt;br /&gt;      return;&lt;br /&gt;&lt;br /&gt;    //setup onActivity handler to get notification of mic activity&lt;br /&gt;    mic.onActivity = function(active:Boolean)&lt;br /&gt;    {   &lt;br /&gt;      //call out to JavaScript bridge via ExternalInterface&lt;br /&gt;      flash.external.ExternalInterface.call("IsTalking", active);&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    //create movie clip and attach mic to clip so we can hear output&lt;br /&gt;    this.createEmptyMovieClip("sound_mc", this.getNextHighestDepth());&lt;br /&gt;    sound_mc.attachAudio(active_mic);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  //set the microphone gain as per the isOn input variable&lt;br /&gt;  mic.setGain(isOn ? 50 : 0);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Below the function, add a callback handler that makes the function callable via JavaScript:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;  flash.external.ExternalInterface.addCallback("ToggleVoice", this, toggleVoice);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Html: Application host page&lt;/b&gt;&lt;br /&gt;When you add a Silverlight application to your solution in Visual Studio, the boilerplate html makes your application full-screen in the browser window (as in the Tutor.com Classroom); this is exactly what we ant. Next, we need to add our Flash html object tag. Silverlight is a bit picky about where you add this html tag since you need to preserve this 100% height style, so slot the Flash object tag immediately before the div tag, and style it with "position:absolute" so that it doesn't interfere in the html layout:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;  &amp;lt;form id="form1" runat="server" style="height:100%;"&amp;gt;&lt;br /&gt;    &amp;lt;asp:ScriptManager ID="ScriptManager1" runat="server" /&amp;gt;&lt;br /&gt;            &lt;br /&gt;    &amp;lt;object &lt;br /&gt;      id="voice" &lt;br /&gt;      style="position:absolute;"&lt;br /&gt;      classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"&lt;br /&gt;      codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" &lt;br /&gt;      width="250" &lt;br /&gt;      height="150" &lt;br /&gt;      align="middle"&lt;br /&gt;      ...&lt;br /&gt;    /&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;div style="height:100%;"&amp;gt;&lt;br /&gt;      &amp;lt;asp:Silverlight     &lt;br /&gt;        ID="Xaml1" &lt;br /&gt;        runat="server"                 &lt;br /&gt;        ...&lt;br /&gt;      /&amp;gt;                                &lt;br /&gt;    &amp;lt;/div&amp;gt;&lt;br /&gt;  &amp;lt;/form&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Javascript: Flash/Silverlight bridge&lt;/b&gt;&lt;br /&gt;Next, we'll create the JavaScript function that our Silverlight app will call, which will in turn call into our Flash movie to set the Microphone input status. Since our Flash movie registered the ToggleVoice() callback function using ExternalInterface, Flash added a JavaScript entry point to function when the Flash movie loaded:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;&amp;lt;script language="javascript" type="text/javascript"&amp;gt;&lt;br /&gt;function toggleVoice(on) &lt;br /&gt;{&lt;br /&gt;    var flashVoiceObject = thisMovie("voice");&lt;br /&gt;    if (!flashVoiceObject)&lt;br /&gt;        return;&lt;br /&gt;&lt;br /&gt;    flashVoiceObject.ToggleVoice(on);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function thisMovie(movieName) {&lt;br /&gt;    if (navigator.appName.indexOf("Microsoft") != -1) {&lt;br /&gt;        return document.getElementById(movieName);&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;        return document[movieName];&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can also very simply call from JavaScript into Silverlight, and we'll do this to alert our Silverlight application when Flash notifies us of microphone activity:&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;function IsTalking(active) &lt;br /&gt;{&lt;br /&gt;    //access the Silverlight application&lt;br /&gt;    var control = document.getElementById("Xaml1");&lt;br /&gt;&lt;br /&gt;    control.Content.Page.ToggleIsTalking(active);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Silverlight – Microphone toggle button&lt;/b&gt;&lt;br /&gt;Finally, in Page.xaml, add a toggle button with Checked and Unchecked handlers, and an indicator that we'll show when the microphone is active:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;ToggleButton Content="Toggle Microphone Input" Checked="ToggleVoice_CheckedToggled" Unchecked="ToggleVoice_CheckedToggled" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;TextBlock Text="You are talking..." Visibility="Collapsed" x:Name="IsTalkingIndicator" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then in Page.xaml.cs, implement the handler and call into the JavaScript function:&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;private void ToggleVoice_CheckedToggle(object sender, RoutedEventArgs e)&lt;br /&gt;{&lt;br /&gt;    //call js layer to set microphone state&lt;br /&gt;    ScriptObject voiceToggleScriptObject = (ScriptObject)HtmlPage.Window.GetProperty("toggleVoice");&lt;br /&gt;&lt;br /&gt;    ToggleButton tb = sender as ToggleButton;&lt;br /&gt;    voiceToggleScriptObject.InvokeSelf(tb.IsChecked.Value);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Lastly, implement the ToggleIsTalking() function that we'll call from JavaScript when the Flash movie responds to the microphone's onActivity() event. You just need to decorate this function with the [ScriptableMember] attribute so that Silverlight registers the function with the JavaScript runtime:&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;[ScriptableMember]&lt;br /&gt;public void ToggleVoiceOn(bool On)&lt;br /&gt;{&lt;br /&gt;    IsTalkingIndicator.Visibility = (On) ? Visibility.Visible : Visibility.Collapsed;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And that's it! You now have a relatively straightforward Flash &amp;lt;=&amp;gt;JavaScript &amp;lt;=&amp;gt; Silverlight solution that affords you the best of all worlds.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-529620945685945286?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2009/01/microphone-access-in-silverlight-via.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>17</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-5199801219035423885</guid><pubDate>Tue, 09 Dec 2008 15:43:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.794-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><title>Tutor.com Classroom How-To #11: Build a Silverlight ToolbarButton user control</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;One of the controls missing out-of-the gate from Silverlight is the Toolbar. There is no magic to the WPF Toolbar (it’s just a control container that auto-docks itself and auto-styles its children), but for free you get the flat button look-and-feel that users expect at the top of an application.&lt;br /&gt;&lt;br /&gt;In Silverlight, we have to manually create this look-and-feel. Since our application’s toolbar consists solely of buttons (both normal and toggle buttons), and since the buttons in our toolbar have the “icon followed by a text description” format, we can abstract this to build the ToolbarButton user control.&lt;br /&gt;&lt;br /&gt;Begin by creating a new user control. Define the styles for the Hover and Pressed states in your user control’s Xaml resources:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;UserControl.Resources&amp;gt;&lt;br /&gt;  &amp;lt;LinearGradientBrush x:Key="HoverBrush" StartPoint="0,0" EndPoint="0,1"&amp;gt;&lt;br /&gt;    &amp;lt;LinearGradientBrush.GradientStops&amp;gt;&lt;br /&gt;      &amp;lt;GradientStop Color="White" /&amp;gt;&lt;br /&gt;      &amp;lt;GradientStop Color="#F8D28F" Offset=".3" /&amp;gt;&lt;br /&gt;    &amp;lt;/LinearGradientBrush.GradientStops&amp;gt;&lt;br /&gt;  &amp;lt;/LinearGradientBrush&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;LinearGradientBrush x:Key="PressedBrush" StartPoint="0,0" EndPoint="0,1"&amp;gt;&lt;br /&gt;    &amp;lt;LinearGradientBrush.GradientStops&amp;gt;&lt;br /&gt;      &amp;lt;GradientStop Color="#F8D28F"/&amp;gt;&lt;br /&gt;      &amp;lt;GradientStop Color="White" Offset=".3" /&amp;gt;&lt;br /&gt;    &amp;lt;/LinearGradientBrush.GradientStops&amp;gt;&lt;br /&gt;  &amp;lt;/LinearGradientBrush&amp;gt;&lt;br /&gt;&amp;lt;/UserControl.Resources&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, use a Grid to hold two Border objects; one contains the image and the text label, and the other is a half-opaque, white filled Border that we use when the button is disabled.&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;Grid&amp;gt;&lt;br /&gt;  &amp;lt;Border x:Name="MainBorder" BorderThickness="1" CornerRadius="1" MouseEnter="Border_MouseEnter" MouseLeave="Border_MouseLeave" MouseLeftButtonUp="Border_MouseLeftButtonUp" Cursor="Hand" Margin="1"&amp;gt;&lt;br /&gt;    &amp;lt;StackPanel Orientation="Horizontal" Margin="5,1,5,1"&amp;gt;&lt;br /&gt;      &amp;lt;Image x:Name="BorderImage" Width="16" /&amp;gt;&lt;br /&gt;      &amp;lt;TextBlock x:Name="BorderTextBlock" Style="{StaticResource blackText}" Margin="5" /&amp;gt;&lt;br /&gt;    &amp;lt;/StackPanel&amp;gt;&lt;br /&gt;  &amp;lt;/Border&amp;gt;&lt;br /&gt;  &amp;lt;Border Background="#B2FFFFFF" x:Name="DisabledBackground" BorderThickness="1" CornerRadius="2" BorderBrush="#B2FFFFFF" Visibility="Collapsed" /&amp;gt;&lt;br /&gt;&amp;lt;/Grid&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, wire up the IsEnabled, ToolTip, ImageSource, and Caption properties, and implement the hover and click functionality. Note that these properties are backed by dependency properties on the objects we defined in our Xaml.&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;public partial class ToolbarButton : UserControl&lt;br /&gt;{&lt;br /&gt;  bool m_IsEnabled = true;&lt;br /&gt;&lt;br /&gt;  public new bool IsEnabled&lt;br /&gt;  {&lt;br /&gt;     set&lt;br /&gt;     {&lt;br /&gt;       MainBorder.Background = null;&lt;br /&gt;       MainBorder.BorderBrush = null;&lt;br /&gt;       DisabledBackground.Visibility = (value) ? Visibility.Collapsed : Visibility.Visible;&lt;br /&gt;     }&lt;br /&gt;  }  &lt;br /&gt;&lt;br /&gt;  public string ToolTip&lt;br /&gt;  {&lt;br /&gt;    get { return ToolTipService.GetToolTip(MainBorder).ToString();}&lt;br /&gt;    set { ToolTipService.SetToolTip(MainBorder, value);}&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public ImageSource ImageSource&lt;br /&gt;  {&lt;br /&gt;    get { return BorderImage.Source;}&lt;br /&gt;    set { BorderImage.Source = value;}&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public string Caption&lt;br /&gt;  {&lt;br /&gt;    get { return BorderTextBlock.Text;}&lt;br /&gt;    set { BorderTextBlock.Text = value;}&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public bool IsToggleButton { get; set; }&lt;br /&gt;  public bool IsToggled { get; set; }&lt;br /&gt;&lt;br /&gt;  public event MouseButtonEventHandler Clicked;&lt;br /&gt;&lt;br /&gt;  public ToolbarButton()&lt;br /&gt;  {&lt;br /&gt;    InitializeComponent();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void Border_MouseEnter(object sender, MouseEventArgs e)&lt;br /&gt;  {&lt;br /&gt;    //if we're a toggle button and we're on...&lt;br /&gt;    if (this.IsToggleButton &amp;amp;&amp;amp; this.IsToggled)&lt;br /&gt;      return;&lt;br /&gt;&lt;br /&gt;    Border b = sender as Border;&lt;br /&gt;&lt;br /&gt;    b.Background = Resources["HoverBrush"] as Brush;&lt;br /&gt;    b.BorderBrush = new SolidColorBrush(ColorHelper.FromHexString("FFCA8103"));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void Border_MouseLeave(object sender, MouseEventArgs e)&lt;br /&gt;  {&lt;br /&gt;    //if we're a toggle button and we're on...&lt;br /&gt;    if (this.IsToggleButton &amp;amp;&amp;amp; this.IsToggled)&lt;br /&gt;      return;&lt;br /&gt;&lt;br /&gt;    Border b = sender as Border;&lt;br /&gt;&lt;br /&gt;    b.Background = null;&lt;br /&gt;    b.BorderBrush = null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void Border_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)&lt;br /&gt;  {&lt;br /&gt;    if (!m_IsEnabled)&lt;br /&gt;      return;&lt;br /&gt;&lt;br /&gt;    if (this.IsToggleButton)&lt;br /&gt;    {&lt;br /&gt;      this.IsToggled = !this.IsToggled;&lt;br /&gt;&lt;br /&gt;      //set state&lt;br /&gt;      Border b = sender as Border;&lt;br /&gt;      b.Background = (this.IsToggled) ? Resources["PressedBrush"] as Brush : Resources["HoverBrush"] as Brush;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if (this.Clicked != null)&lt;br /&gt;      this.Clicked(sender, e);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, in your container Xaml, use the ToolbarButton class inside a StackPanel with Orientation set to Horizontal:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;StackPanel Orientation="Horizontal"&amp;gt;&lt;br /&gt;  &amp;lt;local:ToolbarButton ImageSource="/Resources/board.png" Caption="Add Whiteboard" Clicked="AddWhiteboard_Click" Margin="1" /&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/StackPanel&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-5199801219035423885?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/12/tutorcom-classroom-how-to-11-build.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-7044628438739749941</guid><pubDate>Fri, 05 Dec 2008 15:20:00 +0000</pubDate><atom:updated>2008-12-05T14:57:44.489-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">t-sql</category><category domain="http://www.blogger.com/atom/ns#">performance tuning</category><title>default DateTime parameters to an old date, never NULL</title><description>you want to use:&lt;br /&gt;&lt;br /&gt;CREATE PROCEDURE …&lt;br /&gt;@StartDate = ‘1/1/2000’&lt;br /&gt;&lt;br /&gt;not&lt;br /&gt;&lt;br /&gt;CREATE PROCEDURE …&lt;br /&gt;@StartDate = NULL&lt;br /&gt;&lt;br /&gt;the reason for this is that if you use NULL, you have to put WHERE (@StartDate IS NULL OR DateValue &gt; @StartDate) in your where clause, which screws your query optimization. if you default to an old date, you can just put WHERE (DateValue &gt; @StartDate) so the optimizer will be happy—&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-7044628438739749941?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/12/default-datetime-parameters-to-old-date.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-5779808765184026750</guid><pubDate>Fri, 05 Dec 2008 15:20:00 +0000</pubDate><atom:updated>2008-12-05T14:56:54.830-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">source code</category><category domain="http://www.blogger.com/atom/ns#">app design</category><title>beware API overloads</title><description>on business object methods like Consumer.UpdateConsumer() we have several overloads that let you update only a few specific Consumer properties. for example, there’s one overload that takes a CustomerStatusId, another that takes a WhereHeard and a CustomerStatusId, etc. these overloads all call a common, private updateConsumer() function that takes care of the database update, and they pass in the object’s properties for the fields you are not updating, so that the original values are preserved.&lt;br /&gt;&lt;br /&gt;however, this means that if you call an overload that takes multiple parameters, any value you pass in as a parameter will be used for the database update. so passing in “null” or empty string will update the database with “null” or empty string for that field, which may not be your intention--&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-5779808765184026750?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/12/beware-api-overloads.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-4804390623847176337</guid><pubDate>Thu, 04 Dec 2008 19:08:00 +0000</pubDate><atom:updated>2008-12-04T14:15:13.274-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">web server</category><category domain="http://www.blogger.com/atom/ns#">vs2008</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">source code</category><title>beware maxBufferSize, maxReceivedMessageSize, and maxStringCotentLength when adding service reference in VS2008</title><description>when you add a service reference in VS2008, you end up with a &lt;system.serviceModel&gt; entry in your applications app.config file. this element contains binding elements for each service you add.&lt;br /&gt;&lt;br /&gt;BEWARE: the default value for three critical attributes, maxBufferSize, maxReceivedMessageSize, and maxStringCotentLength, is set considerably low (64KB). we have hit this problem more than once now with deployed software, and unfortunately the only way to correct it is to adjust these values in app.config and re-distribute the software. so if you think there is even the slightest chance that your service will be returning more than 64KB in data, be sure to adjust these values after you add the service reference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-4804390623847176337?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/12/beware-maxbuffersize.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-89328560216735540</guid><pubDate>Fri, 14 Nov 2008 13:00:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.795-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">javascript</category><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">html</category><title>Tutor.com Classroom How-To #10: manually detecting and installing the Silverlight plug-in</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;Use the isInstalled() function provided by Silverlight.js:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="jscript"&gt;&lt;br /&gt;&amp;lt;script language="javascript" type="text/javascript"&amp;gt;&lt;br /&gt;&lt;br /&gt;Silverlight.InstallAndCreateSilverlight = function(version)&lt;br /&gt;{&lt;br /&gt;  var retryTimeout = 1000; //the interval at which instantiation is attempted(ms)&lt;br /&gt;  if (Silverlight.isInstalled(version))&lt;br /&gt;  {&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;  else if (!Silverlight.isInstalled(version))&lt;br /&gt;  {&lt;br /&gt;    TimeoutDelegate = function()&lt;br /&gt;    {&lt;br /&gt;      Silverlight.InstallAndCreateSilverlight(version);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    setTimeout(TimeoutDelegate, retryTimeout);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Silverlight.InstallAndCreateSilverlight('2.0.30923.0');&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-89328560216735540?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/manually-detecting-and-installing.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-6919818252528808109</guid><pubDate>Thu, 13 Nov 2008 15:17:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.797-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>Tutor.com Classroom How-To #9: creating a Path object from a Stroke</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;Simply transfer Stroke stylus points to a PolyLineSegment on a Path:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;static Path getPathFromStroke(Stroke str)&lt;br /&gt;{&lt;br /&gt;  //make a path from this stroke&lt;br /&gt;  Path path = new Path();&lt;br /&gt;  PathGeometry pg = new PathGeometry();&lt;br /&gt;&lt;br /&gt;  //start our figure from the first stylus point in the stroke&lt;br /&gt;  PathFigure fg = new PathFigure();&lt;br /&gt;  fg.Segments = new PathSegmentCollection();&lt;br /&gt;  fg.StartPoint = new Point(str.StylusPoints[0].X, str.StylusPoints[0].Y);&lt;br /&gt;&lt;br /&gt;  PolyLineSegment seg = new PolyLineSegment();&lt;br /&gt;&lt;br /&gt;  //add each additional stylus point to the line segment&lt;br /&gt;  for (int x = 1; x &amp;lt; str.StylusPoints.Count; x++)&lt;br /&gt;    StylusPoint sp = str.StylusPoints[x];&lt;br /&gt;&lt;br /&gt;  seg.Points.Add(new Point(sp.X, sp.Y));&lt;br /&gt;&lt;br /&gt;  fg.Segments.Add(seg);&lt;br /&gt;&lt;br /&gt;  pg.Figures = new PathFigureCollection();&lt;br /&gt;  pg.Figures.Add(fg);&lt;br /&gt;&lt;br /&gt;  path.Data = pg;&lt;br /&gt;&lt;br /&gt;  return path;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-6919818252528808109?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/creating-path-object-from-stroke.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-2509216356827588734</guid><pubDate>Wed, 12 Nov 2008 13:00:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.798-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>Tutor.com Classroom How-To #8: trapping and processing mouse movement in an InkPresenter</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;In the MouseDown event, instantiate a module-level Stroke object (e.g. m_DrawingStroke) to collect points traversed by the mouse. Fire the StrokeAdded event so that listeners can prepare for the operation as necessary. Most importantly, call CaptureMouse() to notify the mouse input engine to give you high frequency mouse event notifications.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;void Whiteboard_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)&lt;br /&gt;{&lt;br /&gt;  //get our current position&lt;br /&gt;  Point p = e.GetPosition(this);&lt;br /&gt;&lt;br /&gt;  //create a new styluspoint collection for our new stroke&lt;br /&gt;  StylusPointCollection coll = new StylusPointCollection();&lt;br /&gt;  coll.Add(new StylusPoint() { X = p.X, Y = p.Y });&lt;br /&gt;&lt;br /&gt;  m_DrawingStroke = new Stroke(coll);&lt;br /&gt;&lt;br /&gt;  //fire notification event&lt;br /&gt;  if (this.StrokeAdded != null)&lt;br /&gt;    this.StrokeAdded(m_DrawingStroke);&lt;br /&gt;&lt;br /&gt;  //begin capturing mouse input&lt;br /&gt;  this.CaptureMouse();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In MouseMove, add the traversed point to the Stroke’s StylusPoints collection, and fire the StrokeChanging event to alert interested listeners.&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;void Whiteboard_MouseMove(object sender, MouseEventArgs e)&lt;br /&gt;{&lt;br /&gt;  //get our current position&lt;br /&gt;  Point p = e.GetPosition(this);&lt;br /&gt;&lt;br /&gt;  //add the traversed point to our collection&lt;br /&gt;  StylusPoint sp = new StylusPoint() { X = p.X, Y = p.Y };&lt;br /&gt;  m_DrawingStroke.StylusPoints.Add(sp);&lt;br /&gt;&lt;br /&gt;  //fire notification event&lt;br /&gt;  if (this.StrokeChanging != null)&lt;br /&gt;    this.StrokeChanging(m_DrawingStroke);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In MouseUp, release mouse capture and fire the StrokeComplete event.&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;void Whiteboard_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)&lt;br /&gt;{&lt;br /&gt;  //release mouse capture&lt;br /&gt;  this.ReleaseMouseCapture();&lt;br /&gt;&lt;br /&gt;  //fire notification event&lt;br /&gt;  if (this.StrokeComplete != null)&lt;br /&gt;    this.StrokeComplete(m_DrawingStroke);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-2509216356827588734?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/trapping-and-processing-mouse-movement.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-9189326627072670147</guid><pubDate>Tue, 11 Nov 2008 13:00:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.799-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>Tutor.com Classroom How-To #7: screen-scraping an application via Win32 PrintWindow() API</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;In the WPF application, we make calls to the PrintWindow() Win32 API to gather screen contents. We then splice the return bitmap into a 4x4 grid and compare hashes of each of the slices with the previous slices’ hashes. If a slice has changed, we package up its bytes and ship it across the wire.&lt;br /&gt;&lt;br /&gt;There are two key components to making this process of screen scrape, comparison, and messaging fast enough to run each second without overburdening the CPU. The first is that the entire process runs on a thread pool thread via a timer, which frees up the GUI.  The second is that our Bitmap uses the Format32bppArgb pixel format, which uses more memory but optimizes performance of PrintWindow() calls.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;[DllImport("user32.dll", SetLastError = true)]&lt;br /&gt;static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);&lt;br /&gt;&lt;br /&gt;void processCapture()&lt;br /&gt;{&lt;br /&gt;  using (Graphics g = Graphics.FromImage(captureBitmap))&lt;br /&gt;  {&lt;br /&gt;    //get window content&lt;br /&gt;    IntPtr hdc = g.GetHdc();&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;      result = PrintWindow(m_Win32HostHandle, hdc);&lt;br /&gt;    }&lt;br /&gt;    finally&lt;br /&gt;    {&lt;br /&gt;      g.ReleaseHdc(hdc);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    //process captureBitmap&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-9189326627072670147?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/screen-scraping-application-via-win32.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-4501304160828580941</guid><pubDate>Mon, 10 Nov 2008 13:00:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.800-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>Tutor.com Classroom How-To #6: creating a horizontal WrapPanel that is transform-aware and exposes row and column counts</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;Begin by deriving from Panel, which is the base class for container controls, and override the MeasureOverride() and ArrangeOverride() functions. These functions are called iteratively as the layout engine determines how to distribute available visual space. Have them call a custom function that takes either the available size (from the measure pass) or the final size (from the arrange pass), and a ShouldArrange parameter to specify which pass is processing, and returns a Size.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;private Size measureAndOptionallyArrangeItems(Size size, bool ShouldArrange)&lt;br /&gt;{&lt;br /&gt;  Point point = new Point(0, 0);&lt;br /&gt;  Size s = new Size(size.Width, 0);&lt;br /&gt;&lt;br /&gt;  //consider scale transform that might be affecting us&lt;br /&gt;  double xfactor = 1;&lt;br /&gt;  double yfactor = 1;&lt;br /&gt;  if (this.RenderTransform != null)&lt;br /&gt;  {&lt;br /&gt;    if (this.RenderTransform is ScaleTransform)&lt;br /&gt;    {&lt;br /&gt;      ScaleTransform st = (ScaleTransform)this.RenderTransform;&lt;br /&gt;&lt;br /&gt;      xfactor = st.ScaleX;&lt;br /&gt;      yfactor = st.ScaleY;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;  double largestHeight = 0.0;&lt;br /&gt;&lt;br /&gt;  this.Rows = 0;&lt;br /&gt;  this.Cols = 0;&lt;br /&gt;&lt;br /&gt;  foreach (UIElement child in Children)&lt;br /&gt;  {&lt;br /&gt;    if (child.DesiredSize.Height &gt; largestHeight)&lt;br /&gt;      largestHeight = child.DesiredSize.Height;&lt;br /&gt;&lt;br /&gt;    //first row?&lt;br /&gt;    if (this.Rows == 0)&lt;br /&gt;      this.Rows = 1;&lt;br /&gt;&lt;br /&gt;    double desiredWidth = child.DesiredSize.Width;&lt;br /&gt;&lt;br /&gt;    //does this child cause us to wrap?&lt;br /&gt;    if (point.X &gt; 0 &amp;amp;&amp;amp; point.X + desiredWidth &gt; size.Width * (1 / xfactor))&lt;br /&gt;    {&lt;br /&gt;      this.Rows++;&lt;br /&gt;&lt;br /&gt;      s.Height += largestHeight * yfactor;&lt;br /&gt;&lt;br /&gt;      //goto the next line&lt;br /&gt;      point.X = 0;&lt;br /&gt;      point.Y += largestHeight;&lt;br /&gt;      largestHeight = child.DesiredSize.Height;&lt;br /&gt;&lt;br /&gt;      if (ShouldArrange)&lt;br /&gt;        child.Arrange(new Rect(point, new Point(point.X + desiredWidth, point.Y + child.DesiredSize.Height)));&lt;br /&gt;&lt;br /&gt;      //set our current location in this new line&lt;br /&gt;      point.X = desiredWidth;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;      if (ShouldArrange)&lt;br /&gt;        child.Arrange(new Rect(point, new Point(point.X + desiredWidth, point.Y + child.DesiredSize.Height)));&lt;br /&gt;&lt;br /&gt;      point.X = point.X + desiredWidth;&lt;br /&gt;&lt;br /&gt;      //if we're doing first row, set columns&lt;br /&gt;      if (this.Rows == 1)&lt;br /&gt;        this.Cols++;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  s.Height += largestHeight * yfactor;&lt;br /&gt;&lt;br /&gt;  return s;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-4501304160828580941?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/creating-horizontal-wrappanel-that-is.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-8423588322588551968</guid><pubDate>Fri, 07 Nov 2008 14:44:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.801-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">performance tuning</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>Tutor.com Classroom How-To #5: providing automatic reader-to-writer lock upgrade</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf" target="_blank"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1" target="_blank"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;Create a class that contains a module-level System.Threading.ReaderWriterLock (e.g. m_Lock) and wrap the AcquireReaderLock() function. Then create an AcquireWriterLock() function that returns a LockCookie wrapper (SafeLockCookie), checks to see if the read lock is held, and upgrades if necessary, and a ReleaseWriterLock()function that processes the SafeLockCookie and releases the lock or downgrades back to read:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;public SafeLockCookie AcquireWriterLock()&lt;br /&gt;{&lt;br /&gt;  //if we have a read lock, upgrade&lt;br /&gt;  if (m_Lock.IsReaderLockHeld)&lt;br /&gt;  {&lt;br /&gt;    return new SafeLockCookie(m_Lock.UpgradeToWriterLock(TIMEOUT_MS));&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    m_Lock.AcquireWriterLock(TIMEOUT_MS);&lt;br /&gt;  return null;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void ReleaseWriterLock(SafeLockCookie SafeLockCookie)&lt;br /&gt;{&lt;br /&gt;  //do we need to downgrade?&lt;br /&gt;  if (SafeLockCookie != null)&lt;br /&gt;  {&lt;br /&gt;    m_Lock.DowngradeFromWriterLock(ref SafeLockCookie.LockCookie);&lt;br /&gt;  }&lt;br /&gt;  else&lt;br /&gt;  {&lt;br /&gt;    m_Lock.ReleaseWriterLock();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then have calling functions request write locks by storing a SafeLockCookie when requesting the lock and returning it when releasing:&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;SafeLockCookie lc = m_Lock.AcquireWriterLock();&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt;  m_Lock.ReleaseWriterLock(lc);&lt;br /&gt;} &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-8423588322588551968?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/create-class-that-contains-module-level.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-6994472082240375357</guid><pubDate>Thu, 06 Nov 2008 14:44:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.802-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">source code</category><category domain="http://www.blogger.com/atom/ns#">app design</category><title>Tutor.com Classroom How-To #4: enforcing an MVC-style architecture</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a target="_blank" href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a target="_blank" href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt; The benefits of MVC-style architecture are numerous: testability, modifiability, simplicity of design, etc., and WPF/Silverlight Xaml “binding” provide an ideal structure to effectively detach the front-end from middle-tier business objects.&lt;br /&gt;&lt;br /&gt;One simple way to enforce MVC-style architecture is to put classes with distinct responsibilities in separate assemblies, and add the minimal set of references only as required by each assembly. This enforces the principle of separation of concerns, since you’ve actually made it impossible for code in one assembly to be concerned with the business of another if it shouldn’t!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-6994472082240375357?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/enforcing-mvc-style-architecture.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-7944538444443296597</guid><pubDate>Wed, 05 Nov 2008 14:29:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.803-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">tcp/ip</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">app design</category><title>Tutor.com Classroom How-To #3: specifying "End-Of-Message" to a TCP/IP listener</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a target="_blank" href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a target="_blank" href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt; Since a TCP/IP Listener is constantly in a listening state, the Listener needs to know when to act on the bytes received. To accomplish this, listen first for 8 ASCII bytes that represent two 32-bit integers specifying the number of bytes the sender is sending, and then continue listening until receiving this number of bytes. This is an easier solution to implement than using a delimiter to specify end-of-message, since you don’t have to worry about delimiter escaping, and since you can specify the exact number of bytes to listen for via the third parameter to SocketAsyncEventArgs.SetBuffer().&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-7944538444443296597?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/specifying-end-of-message-to-tcpip.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-2537015175947192063</guid><pubDate>Wed, 05 Nov 2008 01:40:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.808-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">tcp/ip</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">c#</category><title>Tutor.com Classroom How-To #2: connecting to a TCP/IP Listener</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a target="_blank" href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a target="_blank" href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;/blockquote&gt;&lt;br /&gt;Using the Socket class, we just need to create a SocketAsyncEventArgs and call ConnectAsync(). Notice an example of the “#if WPF” directive for subtle Silverlight/WPF differences (as described in the "Code Sharing" post) when we set  the SocketAsyncEventArgs RemoteEndPoint.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;public void Connect(string host, int port)&lt;br /&gt;{&lt;br /&gt;  //instantiate socket&lt;br /&gt;  m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);&lt;br /&gt;&lt;br /&gt;  //set up endpoint&lt;br /&gt;#if WPF&lt;br /&gt;    m_SocketSendArgs.RemoteEndPoint = new IPEndPoint(Dns.GetHostAddresses(host)[0], port);&lt;br /&gt;#else&lt;br /&gt;    m_SocketSendArgs.RemoteEndPoint = new DnsEndPoint(host, port);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;  //set up args&lt;br /&gt;  SocketAsyncEventArgs args = new SocketAsyncEventArgs();&lt;br /&gt;&lt;br /&gt;  args.UserToken = m_Socket;&lt;br /&gt;  args.RemoteEndPoint = m_SocketSendArgs.RemoteEndPoint;&lt;br /&gt;  args.Completed += new EventHandler&lt;socketasynceventargs&gt;(OnConnect);&lt;br /&gt;&lt;br /&gt;  m_Socket.ConnectAsync(args);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-2537015175947192063?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/connecting-to-tcpip-listener.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-2799033726898346115</guid><pubDate>Tue, 04 Nov 2008 01:39:00 +0000</pubDate><atom:updated>2009-01-21T09:29:14.809-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">vs2008</category><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">.net</category><category domain="http://www.blogger.com/atom/ns#">source code</category><title>Tutor.com Classroom How-To #1: sharing code between Silverliht and WPF applications</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a target="_blank" href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a target="_blank" href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt; To actually share the code, use compile-time code sharing by choosing “Add As Link” when adding project files, rather than using our source code management’s “Share”. Using the “Add As Link” technique ensures that as changes are made to shared code, successfully building the solution guarantees that the changes are valid across all three applications. Source code management “Share” requires developers to check in their changes, do a “Get Latest Version” on the shared files, rebuild the solution, make any necessary changes, repeat, etc. In the meantime, the build is potentially broken.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-2799033726898346115?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/sharing-code-between-silverlight-and.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>1</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-7100834502712319745</guid><pubDate>Mon, 03 Nov 2008 13:00:00 +0000</pubDate><atom:updated>2009-01-21T09:29:56.910-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">tutor.com classroom</category><title>The Tutor.com Classroom: How-To tips from the field</title><description>&lt;blockquote&gt;These How-To tips are taken from &lt;a target="_blank" href="http://www.russellgreenspan.com/software/The_Tutor.com_Classroom.pdf"&gt;The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;You can &lt;a target="_blank" href="http://www.tutor.com/Classroom/SLDetector.aspx?Practice=1"&gt;check out the Silverlight Tutor.com Classroom in "practice" mode&lt;/a&gt;, although the real experience is with a live tutor on the other side!&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt; Tutor.com’s online learning system, the Tutor.com Classroom, utilizes many of the advanced capabilities of the Microsoft .NET 3.5 platform, including TCP/IP sockets and WPF, in addition to making full use of the Silverlight browser plug-in. The next set of blog postings show solutions to some of the more interesting problems and how the potential of .NET was employed.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/sharing-code-between-silverlight-and.html"&gt;Share code between Silverlight and WPF applications&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/enforcing-mvc-style-architecture.html"&gt;Enforce an MVC-style architecture&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/connecting-to-tcpip-listener.html"&gt;Connect to a TCP/IP Listener&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/specifying-end-of-message-to-tcpip.html"&gt;Specify “End-Of-Message” to a TCP/IP Listener&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/create-class-that-contains-module-level.html"&gt;Provide automatic reader-to-writer lock upgrade&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/creating-horizontal-wrappanel-that-is.html"&gt;Create a horizontal WrapPanel that is transform-aware and exposes row and column counts&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/screen-scraping-application-via-win32.html"&gt;Screen-scrape an application via Win32 PrintWindow() API&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/trapping-and-processing-mouse-movement.html"&gt;Trap and process mouse movement in an InkPresenter&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/creating-path-object-from-stroke.html"&gt;Create a Path object from a Stroke&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/11/manually-detecting-and-installing.html"&gt;Manually install and detect for the Silverlight plug-in&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://russellgreenspan.blogspot.com/2008/12/tutorcom-classroom-how-to-11-build.html"&gt;Build a Silverlight ToolbarButton user control&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-7100834502712319745?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/11/tutor.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-3357788764774872735</guid><pubDate>Fri, 17 Oct 2008 14:36:00 +0000</pubDate><atom:updated>2008-10-17T11:01:33.446-04:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">wpf</category><title>WPF gotcha: MessageBox.Show() inside Dispatcher.Invoke</title><description>&lt;div class=Section1&gt;  &lt;p class=MsoNormal&gt;in WPF, if you&amp;#8217;re calling MessageBox.Show() inside a Dispatcher.Invoke call (when you&amp;#8217;re moving back to the GUI thread from a worker thread), make sure you pass a Window object for the optional first parameter when calling MessageBox.Show (e.g. &lt;span style='font-size:10.0pt;font-family: "Courier New";color:#2B91AF'&gt;MessageBox&lt;/span&gt;&lt;span style='font-size:10.0pt; font-family:"Courier New"'&gt;.Show(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:#A31515'&gt;&amp;quot;Message Here&amp;quot;&lt;/span&gt;, &lt;span style='color:#A31515'&gt;&amp;quot;Title Here&amp;quot;&lt;/span&gt;);&lt;/span&gt;). if you don&amp;#8217;t, the message box can show up non-modal alongside your app, which is almost never your intent&lt;span style='color:#1F497D'&gt;&amp;#8212;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;&lt;span style='color:#1F497D'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class=MsoNormal&gt;&lt;span style='color:#1F497D'&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-3357788764774872735?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/10/wpf-gotcha-messageboxshow-inside.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-6375808552521251276</guid><pubDate>Thu, 16 Oct 2008 17:48:00 +0000</pubDate><atom:updated>2008-12-05T21:40:43.237-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">.net</category><title>use a specialized Xml writer when creating xml strings</title><description>&lt;div class="Section1"&gt;&lt;p class="MsoNormal"&gt;avoid creating Xml streams by string manipulation (e.g. &lt;span style="font-family:courier new;"&gt;string&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; s = &lt;span style="COLOR: rgb(165,0,33)"&gt;"&amp;lt;Name First='"&lt;/span&gt; + firstName + &lt;span style="COLOR: rgb(165,0,33)"&gt;"' Last='"&lt;/span&gt; + lastName +&lt;span style="COLOR: rgb(165,0,33)"&gt; "'/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: rgb(165,0,33)"&gt;)&lt;/span&gt;, since you get no reserved character escaping and will throw an error when certain input characters are processed.&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;in .NET 3.5, there are two good choices: XDocument (in System.Xml.LINQ) and XmlWriter (in System.Xml). XDocument is particularly powerful, since both it and XElement have param of objects constructors, which means you can specify all elements and each element’s attributes in one statement. it ends up looking very declarative:&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="MARGIN-LEFT: 0.5in;font-family:courier new;" &gt;XDocument xDoc = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR: rgb(43,145,175)"&gt;XDocument&lt;/span&gt;(&lt;br /&gt;&lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR: rgb(43,145,175)"&gt;XElement&lt;/span&gt;(&lt;span style="COLOR: rgb(163,21,21)"&gt;"Name"&lt;/span&gt;,&lt;br /&gt;&lt;span style="color:blue;"&gt; new&lt;/span&gt; &lt;span style="COLOR: rgb(43,145,175)"&gt;XAttribute&lt;/span&gt;(&lt;span style="COLOR: rgb(163,21,21)"&gt;"First"&lt;/span&gt;, firstName),&lt;br /&gt;&lt;span style="color:blue;"&gt; new&lt;/span&gt; &lt;span style="COLOR: rgb(43,145,175)"&gt;XAttribute&lt;/span&gt;(&lt;span style="COLOR: rgb(163,21,21)"&gt;"Last"&lt;/span&gt;, lastName)&lt;br /&gt;));&lt;/p&gt;&lt;p class="MsoNormal" style="MARGIN-LEFT: 0.5in; FONT-FAMILY: courier new"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="MARGIN-LEFT: 0.5in"&gt;&lt;span style="font-family:courier new;"&gt;string&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; encodedXml = xDoc.ToString();&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="MARGIN-BOTTOM: 12pt"&gt;&lt;span style="font-size:0;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;you can use XmlWriter to write directly to a Stream or to a StringBuilder:&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="MARGIN-BOTTOM: 12pt; MARGIN-LEFT: 0.5in"&gt;StringBuilder sb = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR: rgb(43,145,175)"&gt;StringBuilder&lt;/span&gt;();&lt;span style="color:blue;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="MARGIN-LEFT: 0.5in;font-family:courier new;" &gt;using (&lt;span style="COLOR: rgb(43,145,175)"&gt;XmlWriter&lt;/span&gt; writer = &lt;span style="COLOR: rgb(43,145,175)"&gt;XmlWriter&lt;/span&gt;.Create(sb, &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR: rgb(43,145,175)"&gt;XmlWriterSettings&lt;/span&gt;() { OmitXmlDeclaration = &lt;span style="color:blue;"&gt;true&lt;/span&gt; } ))&lt;br /&gt;{&lt;br /&gt;writer.WriteStartElement(&lt;span style="COLOR: rgb(163,21,21)"&gt;"Name"&lt;/span&gt;);&lt;br /&gt;writer.WriteAttributeString(&lt;span style="COLOR: rgb(163,21,21)"&gt;"First"&lt;/span&gt;, firstName);&lt;br /&gt;writer.WriteAttributeString(&lt;span style="COLOR: rgb(163,21,21)"&gt;"Id"&lt;/span&gt;, lastName);&lt;br /&gt;writer.WriteEndElement();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue;"&gt;string&lt;/span&gt; encodedXml = sb.ToString();&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" face="courier new"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;p class="MsoNormal" face="courier new"&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-6375808552521251276?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/10/use-specialized-xml-writer-when.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-8134680341505762758.post-3066150997561842048</guid><pubDate>Tue, 30 Sep 2008 18:02:00 +0000</pubDate><atom:updated>2008-12-05T21:41:51.587-05:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">wpf</category><category domain="http://www.blogger.com/atom/ns#">silverlight</category><category domain="http://www.blogger.com/atom/ns#">performance tuning</category><title>make sure you manually stop storyboards on hidden objects</title><description>&lt;div class="Section1"&gt;&lt;p class="MsoNormal"&gt;storyboards continue to run even if the object you’re animating is invisible, so you’re generally burning CPU cycles for nothing. in silverlight, you can stop any storyboard just by calling Stop:&lt;?xml:namespace prefix = o /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class="MsoNormal"&gt;myStoryboard.Begin();&lt;br /&gt;myStoryboard.Stop();&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal"&gt;in WPF, you need to specifically let the runtime know that you want Stop functionality when you call Begin via the isControllable paramater:&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class="MsoNormal"&gt;myStoryboard.Begin(this, true);&lt;br /&gt;myStoryboard.Stop();&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class="MsoNormal"&gt;&lt;o:p&gt;&lt;/o:p&gt; &lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8134680341505762758-3066150997561842048?l=russellgreenspan.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://russellgreenspan.blogspot.com/2008/09/make-sure-you-manually-stop-storyboards.html</link><author>noreply@blogger.com (raulgspan)</author><thr:total>0</thr:total></item></channel></rss>

