<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.microsoft.co.il/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Just code - Tamir Khason : Work process, Microsoft</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/Microsoft/default.aspx</link><description>Tags: Work process, Microsoft</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>New year – new blog or how to migrate Community Server to any other engine, supports XML-RPC</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2009/01/01/new-year-new-blog-or-how-to-migrate-community-server-to-any-other-engine-supports-xml-rpc.aspx</link><pubDate>Fri, 02 Jan 2009 02:33:04 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:205248</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Please update your bookmarks, because the new url of this blog is &lt;a href="http://khason.net/"&gt;http://khason.net/&lt;/a&gt; (you have not update RSS feeds, it will be done automatically). Why I did it? Why I decided to go to “stand-alone”… Well. there are some reasons. Generally, I do not want to explain all those here, but trust me, there are some. The main reason is, that there is no responsible person in charge for this blog platform in Microsoft Israel. This why, if your blog is popular and you have a respect to your blog visitors, you cannot host it here… Take a look into new comments notifications in my inbox. Would you answer your readers with such “small amount” of SPAM and capcha, that cannot be fixed already for three years in this platform? This how my inbox looks like for last three years. So now, you should not ask me, why I not answered your email or comments. Aren’t you? :)&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Capture" border="0" alt="Capture" src="http://blogs.microsoft.co.il/blogs/tamir/Capture_1D7350A7.jpg" width="354" height="397" /&gt; &lt;/p&gt;  &lt;p&gt;Currently, all comments in this blog are disabled, so if you want to comment, please use new url of posts (this will appear shortly in the beginning of each post). Also, this post will not be syndicated in RSS.&lt;/p&gt;  &lt;p&gt;So, this post is the last. I loved this platform, and loved people started it. But, unfortunately, it seemed, that bloggers community is not important enough for new platform managers. &lt;/p&gt;  &lt;p&gt;Also, If you want to learn &lt;a target="_blank" href="http://khason.net/dev/how-to-migrate-from-cs2007-to-wordpress-movable-type-or-any-other-blog-engine-supports-xml-rpc-with-c/"&gt;how to use C# and XML-RCP to migrate from CS2007, used in this platform, visit my new home&lt;/a&gt; :)&lt;/p&gt;  &lt;p&gt;Have a great year and, as always, be good people. This post marked with all possible tags automatically. Sorry.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=205248" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/soft/default.aspx">soft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+tools/default.aspx">blogging tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF+crossbow/default.aspx">WPF crossbow</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/help/default.aspx">help</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Gadgets/default.aspx">Windows Gadgets</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Vista/default.aspx">Vista</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/thoughts/default.aspx">thoughts</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tools/default.aspx">tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/events/default.aspx">events</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/demos/default.aspx">demos</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF_2F00_E/default.aspx">WPF/E</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/download/default.aspx">download</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/jobs/default.aspx">jobs</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/VSTS/default.aspx">VSTS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Accessibility/default.aspx">Accessibility</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Blogging+rules/default.aspx">Blogging rules</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/fun/default.aspx">fun</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Vista+Battery+Saver/default.aspx">Vista Battery Saver</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/SkyDrive/default.aspx">SkyDrive</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Live+Writer/default.aspx">Windows Live Writer</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Live/default.aspx">Windows Live</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Dell/default.aspx">Dell</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DevAcademy2/default.aspx">DevAcademy2</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF+quiz/default.aspx">WPF quiz</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/x64/default.aspx">x64</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WF/default.aspx">WF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/SVG/default.aspx">SVG</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XPS/default.aspx">XPS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TechedIsrael2008/default.aspx">TechedIsrael2008</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/teched/default.aspx">teched</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XNA/default.aspx">XNA</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Micro+Framework/default.aspx">Micro Framework</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/SAP/default.aspx">SAP</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XLINQ/default.aspx">XLINQ</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DirectX/default.aspx">DirectX</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Linux/default.aspx">Linux</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mono/default.aspx">Mono</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DevAcademy3/default.aspx">DevAcademy3</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Math/default.aspx">Math</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/GIS/default.aspx">GIS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Algorithms/default.aspx">Algorithms</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TECH/default.aspx">TECH</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Charity/default.aspx">Charity</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/OFFTOPIC/default.aspx">OFFTOPIC</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Hardware/default.aspx">Hardware</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Interop/default.aspx">Interop</category></item><item><title>Capturing and streaming sound by using DirectSound with C#</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/12/25/capturing-and-streaming-sound-by-using-directsound-with-c.aspx</link><pubDate>Thu, 25 Dec 2008 23:48:20 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:201052</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>3</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/capturing-and-streaming-sound-by-using-directsound-with-c/"&gt;http://khason.net/blog/capturing-and-streaming-sound-by-using-directsound-with-c/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;I already wrote a little about &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/02/17/sound-tone-and-dtmf-generation-by-using-managed-directsound-and-c-and-sine-tone-detection-with-pure-managed-goertzel-algorithm-implementation.aspx"&gt;managed way to use DirectX DirectSound&lt;/a&gt;. Today we’ll speak about how to get sound from your microphone or any other DirectSound capturing device (such as &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/12/12/reading-and-decoding-rds-radio-data-system-in-c.aspx"&gt;FM receiver&lt;/a&gt;) and stream it out to your PC speakers and any other DirectSound Output device. So, let’s start creating our first echo service by using managed DirectX.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/image_13541F81.png" width="225" height="229" /&gt; &lt;/p&gt;  &lt;p&gt;First of all we should decide what Wave format we want to use for capturing and recording. So, let’s choose anything reasonable :)&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var format = new WaveFormat {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SamplesPerSecond = 96000,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; BitsPerSample = 16,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Channels = 2,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FormatTag = WaveFormatTag.Pcm      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; };&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now, we should calculate block align and average byte per second value for this format. I’m wondering why it cannot be done automatically…&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;format.BlockAlign = (short)(format.Channels * (format.BitsPerSample / 8));     &lt;br /&gt;format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlign;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Next step is to set the size of two buffers – one for input and other for output. Generally those buffers are circular, and capturing one should be twice bigger, then output. Why? Because we choose two channels to use. Also, we should decide about chunk size of the buffer, we want to signal when filled.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;_dwNotifySize = Math.Max(4096, format.AverageBytesPerSecond / 8);     &lt;br /&gt;_dwNotifySize -= _dwNotifySize % format.BlockAlign;      &lt;br /&gt;_dwCaptureBufferSize = NUM_BUFFERS * _dwNotifySize;      &lt;br /&gt;_dwOutputBufferSize = NUM_BUFFERS * _dwNotifySize / 2;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Next step is to create CaptureBufferDescriptor and actual capturing buffer. We’ll enumerate all devices and choose one, satisfies given string (captureDescriptor) – for example “Mic” :)&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var cap = default(Capture);     &lt;br /&gt;var cdc = new CaptureDevicesCollection();      &lt;br /&gt;for (int i = 0; i &amp;lt; cdc.Count; i++) {      &lt;br /&gt;&amp;#160;&amp;#160; if (cdc[i].Description.ToLower().Contains(captureDescriptor.ToLower())) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; cap = new Capture(cdc[i].DriverGuid);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;      &lt;br /&gt;&amp;#160;&amp;#160; }      &lt;br /&gt;}      &lt;br /&gt;var capDesc = new CaptureBufferDescription {      &lt;br /&gt;&amp;#160;&amp;#160; Format = format,      &lt;br /&gt;&amp;#160;&amp;#160; BufferBytes = _dwCaptureBufferSize      &lt;br /&gt;};      &lt;br /&gt;_dwCapBuffer = new CaptureBuffer(capDesc, cap);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Then we’ll create output device and buffer. To simplify program, we will use default speakers to output, however, you can choose output device the same way we did for capturing. Also, because DirectSound uses any window as it’s message pump, we have to use SetCooperativeLevel method. In my case (windowless application), I’ll use desktop window as message broker. This why you will have to add Windows.Forms as reference for your project, even if it console application. Also, do not forget to set GlobalFocus value to True, if you want to play echo, even if desktop window is not focused.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var dev = new Device();     &lt;br /&gt;dev.SetCooperativeLevel(Native.GetDesktopWindow(), CooperativeLevel.Priority); &lt;/p&gt;    &lt;p&gt;var devDesc = new BufferDescription {     &lt;br /&gt;&amp;#160;&amp;#160; BufferBytes = _dwOutputBufferSize,      &lt;br /&gt;&amp;#160;&amp;#160; Format = format,      &lt;br /&gt;&amp;#160;&amp;#160; DeferLocation = true,      &lt;br /&gt;&amp;#160;&amp;#160; GlobalFocus = true      &lt;br /&gt;};      &lt;br /&gt;_dwDevBuffer = new SecondaryBuffer(devDesc, dev);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now, we will subscribe to buffer notifications and set autoResetEvent to be fired when it filled up.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;var _resetEvent = new AutoResetEvent(false);     &lt;br /&gt;var _notify = new Notify(_dwCapBuffer);      &lt;br /&gt;//half&amp;amp;half      &lt;br /&gt;var bpn1 = new BufferPositionNotify();      &lt;br /&gt;bpn1.Offset = _dwCapBuffer.Caps.BufferBytes / 2 - 1;      &lt;br /&gt;bpn1.EventNotifyHandle = _resetEvent.SafeWaitHandle.DangerousGetHandle();      &lt;br /&gt;var bpn2 = new BufferPositionNotify();      &lt;br /&gt;bpn2.Offset = _dwCapBuffer.Caps.BufferBytes - 1;      &lt;br /&gt;bpn2.EventNotifyHandle = _resetEvent.SafeWaitHandle.DangerousGetHandle(); &lt;/p&gt;    &lt;p&gt;_notify.SetNotificationPositions(new BufferPositionNotify[] { bpn1, bpn2 });&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Almost done, the only thing we should do is to fire worker thread to take care on messages&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;int offset = 0;     &lt;br /&gt;_dwCaptureThread = new Thread((ThreadStart)delegate {      &lt;br /&gt;&amp;#160;&amp;#160; _dwCapBuffer.Start(true); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160; while (IsReady) {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _resetEvent.WaitOne();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; var read = _dwCapBuffer.Read(offset, typeof(byte), LockFlag.None, _dwOutputBufferSize);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _dwDevBuffer.Write(0, read, LockFlag.EntireBuffer);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; offset = (offset + _dwOutputBufferSize) % _dwCaptureBufferSize;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _dwDevBuffer.SetCurrentPosition(0);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; _dwDevBuffer.Play(0, BufferPlayFlags.Default);      &lt;br /&gt;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160; _dwCapBuffer.Stop();      &lt;br /&gt;});      &lt;br /&gt;_dwCaptureThread.Start();&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;That’s it. Compile and run. Now if you’ll speak, you can hear your echo from PC speakers. &lt;/p&gt;  &lt;p&gt;Merry Christmas for whom concerns and be good people – do not scare your co-workers with strange sounds – be polite and make the volume lower :) &lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=201052" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DirectX/default.aspx">DirectX</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Hardware/default.aspx">Hardware</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Interop/default.aspx">Interop</category></item><item><title>Quick Silverlight (and WPF) tip: How to write program without XAML</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/12/23/quick-silverlight-and-wpf-tip-how-to-write-program-without-xaml.aspx</link><pubDate>Tue, 23 Dec 2008 23:51:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:199696</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>2</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/quick-silverlight-and-wpf-tip-how-to-write-program-without-xaml/"&gt;http://khason.net/blog/quick-silverlight-and-wpf-tip-how-to-write-program-without-xaml/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;From the moment, &lt;a href="http://2009.visitmix.com/MIXtify/TenKGallery.aspx"&gt;10K MIX09 contest was launched&lt;/a&gt;, I got more, then 20 people, asking the same question: &lt;b&gt;Is it possible to have Silverlight program up and running without XAML at all?&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://blogs.microsoft.co.il/blogs/tamir/image_5432FC95.png" style="border:0px none;display:inline;" title="image" alt="image" width="315" border="0" height="289" /&gt; &lt;/p&gt;  &lt;p&gt;The answer is “&lt;b&gt;YES, IT IS&lt;/b&gt;”. Here is how:&lt;/p&gt;  &lt;p&gt;All you need for run WPF or Silverlight application is &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Class inherited from System.Windows.Application&lt;/li&gt;    &lt;li&gt;Class inherited from System.Windows.Controls.UserControl&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;So, Let’s create new WPF or Silverlight application and delete all files from the project directory. Then add one file, named App.cs (or Foo.cs or Whatever.cs – the length of the file name is not included :) ) and write there :&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;using System.Windows.Controls;     &lt;br /&gt;using System.Windows;&lt;/p&gt;    &lt;p&gt;public class App : Application {public App() {this.Startup += (s, e) =&amp;gt; { this.RootVisual = Foo.M; };}}&amp;nbsp; &lt;br /&gt;class Foo: UserControl {static Foo _b = new Foo();public static Board M { get { return _b; } }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We done. F5, be happy. You just wrote first officially smallest Silverlight functional application. Good luck with Mix09 contest.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=199696" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/fun/default.aspx">fun</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category></item><item><title>How to P/Invoke VarArgs (variable arguments) in C#? ... or hidden junk in CLR</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/11/19/how-to-p-invoke-varargs-variable-arguments-in-c-or-hidden-junk-in-clr.aspx</link><pubDate>Wed, 19 Nov 2008 11:44:10 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:170664</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>1</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/how-to-pinvoke-varargs-variable-arguments-in-c-or-hidden-junk-in-clr/"&gt;http://khason.net/blog/how-to-pinvoke-varargs-variable-arguments-in-c-or-hidden-junk-in-clr/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Recently I &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/10/20/p-invoke-cheat-sheet.aspx"&gt;wrote a cheat sheet for pinvoking in .NET&lt;/a&gt;. Shortly after I got a question in comments about how to deal with variable arguments, when it&amp;#39;s more, then one parameter. Also what to do if those arguments are heterogeneous? &lt;/p&gt; &lt;p&gt;Let&amp;#39;s say, that we have following method in C:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;int VarSum(int nargs, ...){&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; va_list argp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; va_start( argp, nargs );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int sum = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( int i = 0 ; i &amp;lt; nargs; i++ ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int arg = va_arg( argp, int );&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sum += arg;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; va_end( argp );  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return sum;&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;We can expose this method to C# as following:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;[System.Runtime.InteropServices.DllImportAttribute(&amp;quot;unmanaged.dll&amp;quot;, EntryPoint = &amp;quot;VarSum&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static extern int VarSum(int nargs,int arg1); &lt;p&gt;[System.Runtime.InteropServices.DllImportAttribute(&amp;quot;unmanaged.dll&amp;quot;, EntryPoint = &amp;quot;VarSum&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static extern int VarSum(int nargs,int arg1,int arg2);&lt;/p&gt; &lt;p&gt;[System.Runtime.InteropServices.DllImportAttribute(&amp;quot;unmanaged.dll&amp;quot;, EntryPoint = &amp;quot;VarSum&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static extern int VarSum(int nargs,int arg1,int arg2,int arg3);&lt;/p&gt; &lt;p&gt;etc...&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And it will work. However, if you&amp;#39;ll try to expose it as int array, marshaller will fail to understand how to align things&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;[System.Runtime.InteropServices.DllImportAttribute(&amp;quot;unmanaged.dll&amp;quot;, EntryPoint = &amp;quot;VarSum&amp;quot;)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static extern int VarSum(int nargs,int[] arg);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This in spite of the fact, that this method will work properly with another signature&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;int ArrSum(int* nargs) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int sum = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( int i = 0 ; i &amp;lt; 2; i++ ) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sum += nargs[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return sum;&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;So what to do? The &lt;u&gt;official&lt;/u&gt; answer is - &lt;strong&gt;you have nothing to do, rather then override all possibilities&lt;/strong&gt;. This is very bad and absolutely not flexible. So, there is small class in C#, named ArgIterator. This one is similar to params object[], but knows to marshal into varargs. The problem is, that you have no way to add things inside. It&amp;#39;s &amp;quot;kind-of-read-only&amp;quot;. &lt;/p&gt; &lt;p&gt;Let&amp;#39;s look into reflected version of ArgIterator. We&amp;#39;ll see there something, named &lt;strong&gt;__arglist and __refvalue&lt;/strong&gt;. OMG, isn&amp;#39;t it good old stuff similar to &amp;quot;__declspec(dllexport) int _stdcall&amp;quot; etc.? It is! But can we use it in C#? We can! Just sign your method as Cdecl and you have working signature for &amp;quot;...&amp;quot;&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;[System.Runtime.InteropServices.DllImportAttribute(&amp;quot;unmanaged.dll&amp;quot;, EntryPoint = &amp;quot;VarSum&amp;quot;, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CallingConvention=System.Runtime.InteropServices.CallingConvention.Cdecl)]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static extern int VarSum(int nargs, __arglist);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Yes, looks strange, and absolutely not CLR compliant. However, this is the only way to expose varargs to CLR via P/Invoke. How to use it? Simple:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;c = VarSum(2, __arglist(5, 10));&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Have a nice day and be good people. Also, my question to Microsoft is why this stuff is not in MSDN and we, as developers, have no way to get rid of it. &lt;/p&gt; &lt;p&gt;Is not it very good practices to use non-compliant methods? Give us another way to do it!&lt;br /&gt;Is not it very good practices to use variable arguments in unmanaged method signatures? So why you want dynamic types in C# 4?&lt;/p&gt; &lt;p&gt;&lt;a href="http://cid-4e39ecd492e4eec1.skydrive.live.com/self.aspx/Public/VarArgsMarshaller.zip%20"&gt;Source code for this article&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=170664" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Interop/default.aspx">Interop</category></item><item><title>P/Invoke cheat sheet</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/10/20/p-invoke-cheat-sheet.aspx</link><pubDate>Mon, 20 Oct 2008 20:02:40 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:155503</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>9</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/pinvoke-cheat-sheet/"&gt;http://khason.net/blog/pinvoke-cheat-sheet/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;I’m working a lot with p/invoke, and know how it’s hard to produce correct signature for unmanaged method. So, today I decided to publish basic cheat sheet for methods, parameters and attributes you should use in order to invoke unmanaged methods from managed code without a lot of problems. We start with data type translations. Here the table to understand it.&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2"&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Data type from unmanaged signature&lt;/td&gt;        &lt;td valign="top"&gt;Data type in managed signature&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;int&lt;/td&gt;        &lt;td valign="top"&gt;int         &lt;br /&gt;          &lt;br /&gt;&lt;em&gt;the same with all other simple types such as double, uint, etc or private objects&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;void*&lt;/td&gt;        &lt;td valign="top"&gt;IntPtr&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;int*&lt;/td&gt;        &lt;td valign="top"&gt;ref int         &lt;br /&gt;          &lt;br /&gt;&lt;em&gt;the same with all other simple types such as double, uint, etc &lt;em&gt;or private objects&lt;/em&gt; &lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;char**&lt;/td&gt;        &lt;td valign="top"&gt;ref IntPtr         &lt;br /&gt;          &lt;br /&gt;&lt;em&gt;later, you should get ascii string by using System.Runtime.InteropServices.Marshal.PtrToStringAnsi() method&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;wcar_t**&lt;/td&gt;        &lt;td valign="top"&gt;ref IntPtr         &lt;br /&gt;          &lt;br /&gt;&lt;em&gt;later, you should get ascii string by using System.Runtime.InteropServices.Marshal.PtrToStringUni() method&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;const int*&lt;/td&gt;        &lt;td valign="top"&gt;ref int&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;const char*&lt;/td&gt;        &lt;td valign="top"&gt;[System.Runtime.InteropServices.In()] [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;… &lt;em&gt;(variable argument)&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;[System.Runtime.InteropServices.In()] [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.AsAny)] object&lt;/td&gt;     &lt;/tr&gt;   &lt;/table&gt;  &lt;p&gt;&lt;em&gt;You can use either System.Runtime.InteropServices.In or System.Runtime.InteropServices.Out attribute to specify how arguments should be used.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;Now we done with simple arguments, let’s see what can be done when argument is actually callback or delegate?&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2"&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Unmanaged definition&lt;/td&gt;        &lt;td valign="top"&gt;Managed definition&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;typedef void (*MyCallback)(int Arg)&lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p&gt;[System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]delegate void MyCallback(int Arg)           &lt;br /&gt;&lt;em&gt;Caller cleans stack argument is used to assure, that we can call varargs type function, usually used by API provider. It is very similar to C# overrides for methods. Also you can use StdCall (this is default), ThisCall – stores this first and pushes other parameters on the stack, FastCall – not very supported :(&lt;/em&gt;&lt;/p&gt;       &lt;/td&gt;     &lt;/tr&gt;   &lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;To call all those methods, we should know managed equivalents of unmanaged types. Here the table. The rule is simple – know how many bytes unmanaged type has and find managed type with the same number of bytes. Other words, you can marshal int into IntPtr too…&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2"&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;Unmanaged type&lt;/td&gt;        &lt;td valign="top"&gt;Managed equivalent&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;bool&lt;/td&gt;        &lt;td valign="top"&gt;bool&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;char&lt;/td&gt;        &lt;td valign="top"&gt;sbyte (signed), byte (unsigned)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;wchar_t&lt;/td&gt;        &lt;td valign="top"&gt;char&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;double&lt;/td&gt;        &lt;td valign="top"&gt;double&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;float&lt;/td&gt;        &lt;td valign="top"&gt;single&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;int, long (signed)&lt;/td&gt;        &lt;td valign="top"&gt;Int32&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;int, long (unsigned)&lt;/td&gt;        &lt;td valign="top"&gt;UInt32&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;__int64 (signed)&lt;/td&gt;        &lt;td valign="top"&gt;Int64&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;__int64&lt;/td&gt;        &lt;td valign="top"&gt;UInt64&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;short (signed)&lt;/td&gt;        &lt;td valign="top"&gt;Int16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;short (unsigned)&lt;/td&gt;        &lt;td valign="top"&gt;UInt16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;void&lt;/td&gt;        &lt;td valign="top"&gt;void&lt;/td&gt;     &lt;/tr&gt;   &lt;/table&gt;  &lt;p&gt;But not only types are problem in managed/unmanaged transitions. Also structures are aligned differently. For this purpose we can use StructLayout attribute. Even if unmanaged classes are sequential and you used correct managed data types, you can find you with problems in Pack. What “pack” is? Pack is actually slot size in bytes for members of your structure. It can be 0, 1, 2, 4, 8, 16, 32, 64, or 128 and depends on the platform and application setting.&lt;/p&gt;  &lt;p&gt;Now you can see, that it is not very complicated to create managed signatures when you have header of unmanaged assemblies. So go ahead and ask, if I missed something.&lt;/p&gt;  &lt;p&gt;That’s all by now. Have a nice day and be good people.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=155503" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF+crossbow/default.aspx">WPF crossbow</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/x64/default.aspx">x64</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mono/default.aspx">Mono</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category></item><item><title>How to handle thickness</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/07/08/how-to-handle-thickness.aspx</link><pubDate>Wed, 09 Jul 2008 02:07:42 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:114375</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>4</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/how-to-handle-thickness/"&gt;http://khason.net/blog/how-to-handle-thickness/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;&lt;/p&gt;  &lt;p&gt;Yesterday, we &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/07/07/work-process-how-to-use-and-build-type-converters.aspx"&gt;spoke about type converters&lt;/a&gt;. We even, built simple generic enum converter. Today, we’ll create more complicated converter, that very missing in Silverlight – ThicknessConverter. During the post, I also explain about tokenizing values in Silverlight&lt;/p&gt;  &lt;p&gt;&lt;img title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/Howtohandlethickness_13711/image_7aa2208a-269e-487e-8ef4-7713a245679d.png" width="178" height="119" /&gt; &lt;/p&gt;  &lt;h3&gt;What is Thickness ?&lt;/h3&gt;  &lt;p&gt;What is thickness in Silverlight? It’s &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;Border BorderThickness=”6”/&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;or&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;Border BorderThickness=”6,4,3,2”/&amp;gt; or &amp;lt;Border BorderThickness=”6, 4, 3,2”/&amp;gt; or, even &amp;lt;Border BorderThickness=”6; 4; 3 ;2”/&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;How to handle it?&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h3&gt;Tokenizing strings&lt;/h3&gt;  &lt;p&gt;What you seen here is tokenized strings. We have to split them by known token (one and own for each string) and then we can parse it for converter. How to do this? Complicated – too much cases. But, basically, you have to get string, quote character and separator. Don’t forget to check for empty spaces&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;private void Initialize(string str, char quoteChar, char separator)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._str = str;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._strLen = (str == null) ? 0 : str.Length;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._currentTokenIndex = -1;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._quoteChar = quoteChar;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._argSeparator = separator;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while (this._charIndex &amp;lt; this._strLen)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!char.IsWhiteSpace(this._str, this._charIndex))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._charIndex++;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Then we have to scan string to find tokens&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;private void ScanToNextToken(char separator)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (this._charIndex &amp;lt; this._strLen)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; char c = this._str[this._charIndex];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ((c != separator) &amp;amp;&amp;amp; !char.IsWhiteSpace(c))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Exceptions.ThrowInvalidOperationException(&amp;quot;No Separator Found&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int i = 0;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while (this._charIndex &amp;lt; this._strLen)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; c = this._str[this._charIndex];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (c == separator)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._foundSeparator = true;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; i++;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._charIndex++;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (i &amp;gt; 1)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Exceptions.ThrowInvalidOperationException(&amp;quot;Empty Token Found&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!char.IsWhiteSpace(c))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this._charIndex++;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ((i &amp;gt; 0) &amp;amp;&amp;amp; (this._charIndex &amp;gt;= this._strLen))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Exceptions.ThrowInvalidOperationException(&amp;quot;Emply Token Found&amp;quot;);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;why not just split? Because it is not generic solution for strings with empty tokens, which is absolutely invalid. Another reason of using such helper is performance. String operation are not very fast things, thus we’ll check only the number of tokens required for future operations. &lt;/p&gt;  &lt;p&gt;Also, we should make sure, that all tokens are required and get rid of unnecessary parts of the string, such as leading spaces, control characters etc. Now, when we have tokenized string, we can start building converter&lt;/p&gt;  &lt;h3&gt;Building thickness converter&lt;/h3&gt;  &lt;p&gt;Actually, the most significant part of this converter is tokenization , thus the most important override method for such converter is ConvertFromString&lt;/p&gt;  &lt;p&gt;public override object ConvertFromString(string text)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Thickness res = new Thickness();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; TokenizerHelper helper = new TokenizerHelper(text);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; double[] numArray = new double[4];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int index = 0;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while (helper.NextToken())    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (index &amp;gt;= 4)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; index = 5;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; LengthConverter lc = new LengthConverter();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; numArray[index] = (double)lc.ConvertFromString(helper.GetCurrentToken());    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; index++;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (index)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case 1:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; res = new Thickness(numArray[0]); break;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case 2:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; res = new Thickness(numArray[0], numArray[1], numArray[0], numArray[1]); break; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case 4:   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; res = new Thickness(numArray[0], numArray[1], numArray[2], numArray[3]); break;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(Thickness).ThrowConvertFromException(text); break;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return res;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;The only thing to remember is to check whither we can convert from the type received from XAML&lt;/p&gt;  &lt;p&gt;public override bool CanConvertFrom(Type sourceType)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (Type.GetTypeCode(sourceType))    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.Int16:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.UInt16:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.Int32:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.UInt32:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.Int64:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.UInt64:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.Single:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.Double:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.Decimal:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case TypeCode.String:    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return true;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return false;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;Have a nice day and be good people. Stay tuned for future &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx"&gt;work process&lt;/a&gt; items.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=114375" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF_2F00_E/default.aspx">WPF/E</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category></item><item><title>Work process: How to use and build type converters</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/07/07/work-process-how-to-use-and-build-type-converters.aspx</link><pubDate>Tue, 08 Jul 2008 00:58:15 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:113996</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>8</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/work-process-how-to-use-and-build-type-converters/"&gt;http://khason.net/blog/work-process-how-to-use-and-build-type-converters/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Today, I want to start new tag - “&lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx"&gt;Work process&lt;/a&gt;”. Here I’m going to publish partial classes, fixes, small utilities, I’m building for myself or clients to help in work process. &lt;em&gt;I’ll give an example&lt;/em&gt;: currently, I’m working on &lt;a href="http://www.codeplex.com/SilverlightRTL"&gt;BiDi support for Silverlight 2.0&lt;/a&gt; (beta 2 to RTM). During the work process, I need to write different classes, such as converters, string utilities, exception helpers etc. &lt;/p&gt;  &lt;p&gt;&lt;img title="ZK4Y7556" border="0" alt="ZK4Y7556" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/WorkprocessHowtouseandbuildtypeconverter_126DC/200453681-001_3086d77d-7abf-49e4-8fd9-35f091441969.jpg" width="337" height="506" /&gt;&amp;#160; &lt;br /&gt;&lt;font size="1"&gt;&lt;a href="http://www.hendricksonphoto.com/"&gt;© Imaginary copyright by&amp;#160; Noel Hendrickson&lt;/a&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;So, today I’ll public general &lt;strong&gt;type converter for generic classes&lt;/strong&gt;.&lt;/p&gt;  &lt;h3&gt;What is type converter?&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/cc645047(VS.95).aspx"&gt;TypeConverter&lt;/a&gt; is a service attribute, used to help rendering engine to convert XAML string (usually it strings) to the type, you require in your class implementation. Here an example:&lt;/p&gt;  &lt;p&gt;In your custom class you have dependency property of type TextAlignment&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public TextAlignment TextAlignment     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return (TextAlignment)GetValue(TextAlignmentProperty); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set { SetValue(TextAlignmentProperty, value); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;In XAML code it will be used as:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;MyControl TextAlignment=”Left”/&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;But, what you’re actually transfer to your class is string “Left”, when you need enum TextAlignment.Left, how to convert it? This for we’re using type converters&lt;/p&gt;  &lt;h3&gt;Attribute usage&lt;/h3&gt;  &lt;p&gt;In order to “tell” framework to use your type converter, you should mark target property with special attribute TypeConverterAttribute. Also, you can provide default value to your property by using another attribute DefaultValueAttribute. This will looks as following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;[TypeConverter(typeof(MyTextAlignmentTypeConverter))]       &lt;br /&gt;[DefaultValue(TextAlignment.Left)]        &lt;br /&gt;&lt;/strong&gt;public TextAlignment TextAlignment      &lt;br /&gt; {      &lt;br /&gt;&amp;#160; get { return (TextAlignment)GetValue(TextAlignmentProperty); }      &lt;br /&gt;&amp;#160; set { SetValue(TextAlignmentProperty, value); }      &lt;br /&gt; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;How to build type converter&lt;/h3&gt;  &lt;p&gt;In order to build type converter, all you have to do is to build your own class, derived from TypeConverter. It also can be generic class. Then, implement necessary methods, that incorporate your business logic. Like this one, converter any enum value back and forward for TypeConverterAttribute&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public class EnumValueConverter&amp;lt;T&amp;gt; : TypeConverter where T:struct     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; static EnumValueConverter()      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!typeof(T).IsEnum) { Exceptions.ThrowInvalidOperationException(&amp;quot;Cannot use this type for conversion&amp;quot;); }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public override bool CanConvertFrom(Type sourceType)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Type.GetTypeCode(sourceType) == TypeCode.String;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public override object ConvertFrom(object value)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (value == null)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; typeof(T).ThrowConvertFromException(value);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (value is string)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return ConvertFromString(value as string);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return (T)value;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public override object ConvertFromString(string text)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return (T)Enum.Parse(typeof(T), text, true);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public override string ConvertToString(object value)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return Enum.GetName(typeof(T), value);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;Final result&lt;/h3&gt;  &lt;p&gt;Now, when we built converter and know how to use it, we can easily set it to any DependencyProperty requires conversion from / to enum&lt;/p&gt;  &lt;p&gt;[TypeConverter(typeof(EnumValueConverter&amp;lt;LineStackingStrategy&amp;gt;))]   &lt;br /&gt;public LineStackingStrategy LineStackingStrategy    &lt;br /&gt; {    &lt;br /&gt;&amp;#160; get { return (LineStackingStrategy)GetValue(LineStackingStrategyProperty); }    &lt;br /&gt;&amp;#160; set { SetValue(LineStackingStrategyProperty, value); }    &lt;br /&gt; }&lt;/p&gt;  &lt;p&gt;[TypeConverter(typeof(EnumValueConverter&amp;lt;TextAlignment&amp;gt;))]   &lt;br /&gt;[DefaultValue(TextAlignment.Right)]    &lt;br /&gt; public TextAlignment TextAlignment    &lt;br /&gt;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160; get { return (TextAlignment)GetValue(TextAlignmentProperty); }    &lt;br /&gt;&amp;#160;&amp;#160; set { SetValue(TextAlignmentProperty, value); }    &lt;br /&gt;&amp;#160; }&lt;/p&gt;  &lt;p&gt;[TypeConverter(typeof(EnumValueConverter&amp;lt;TextWrapping&amp;gt;))]   &lt;br /&gt;public TextWrapping TextWrapping    &lt;br /&gt; {    &lt;br /&gt;&amp;#160; get { return (TextWrapping)GetValue(TextWrappingProperty); }    &lt;br /&gt;&amp;#160; set { SetValue(TextWrappingProperty, value); }    &lt;br /&gt; }&lt;/p&gt;  &lt;p&gt;We done, have a nice day and be good people.&lt;/p&gt;  &lt;p&gt;Stay tuned for release of BiDi support for Silverlight 2.0, sponsored by Development Platform Evangelism unit of Microsoft Israel&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=113996" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF_2F00_E/default.aspx">WPF/E</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category></item></channel></rss>