<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>.NET</title>
        <link>http://geekswithblogs.net/hinshelm/category/4869.aspx</link>
        <description>
	The .NET Framework is Microsoft&amp;#39;s platform for building applications that 
	have visually stunning user experiences, seamless and secure communication, 
	and the ability to model a range of business processes. By providing you 
	with a comprehensive and consistent programming model and a common set of 
	APIs, the .NET Framework helps you to build applications that work the way 
	you want, in the programming language you prefer, across software, services, 
	and devices. 
	
	
	Learn more about .NET Framework </description>
        <language>en-GB</language>
        <copyright>Martin Hinshelwood (SSW)</copyright>
        <managingEditor>martin@hinshelwood.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <creativeCommons:license>http://creativecommons.org/licenses/by/3.0/</creativeCommons:license>
        <item>
            <title>Wpf Scale Transform Behaviour</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/08/31/wpf-scale-transform-behaviour.aspx</link>
            <description>&lt;p&gt;Although this post is called Scale Transform Behaviour you could use any transform / animation in its place. The purpose is to have a slider control in a menu be able to alter the scale of any number of controls within &lt;a href="http://joshsmithonwpf.wordpress.com/2008/12/01/the-philosophies-of-mvvm/" target="_blank"&gt;MVVM&lt;/a&gt; views.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfScaleTransformBehaviour_7143/image_7b0c0350-7e54-4e04-8473-2a22be3f2b81.png" width="281" height="329" /&gt; &lt;/p&gt;  &lt;p&gt;This behaviour allows you to add any Framework Elements to a list of attached controls by adding an attached property of GlobalScaleTransformBehaviour.IsScaled to your controls. &lt;/p&gt;  &lt;pre class="brush: vb;"&gt;Public Class GlobalScaleTransformBehaviour

    Private Shared sm_AttachedControls As List(Of FrameworkElement)
    Public Shared ReadOnly IsScaledProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsScaled", GetType(Boolean), GetType(GlobalScaleTransformBehaviour), New UIPropertyMetadata(False, New PropertyChangedCallback(AddressOf GlobalScaleTransformBehaviour.IsScaledChanged)))
    Private Shared sm_CurrentScale As Double = 1

    Shared Sub New()
        sm_AttachedControls = New List(Of FrameworkElement)
    End Sub

    Public Shared Function GetIsScaled(ByVal element As DependencyObject) As Boolean
        If element Is Nothing Then
            Throw New ArgumentNullException("element")
        End If

        Return element.GetValue(IsScaledProperty)
    End Function

    Public Shared Sub SetIsScaled(ByVal element As DependencyObject, ByVal value As Boolean)
        If element Is Nothing Then
            Throw New ArgumentNullException("element")
        End If
        element.SetValue(IsScaledProperty, value)
    End Sub

    Private Shared Sub IsScaledChanged(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim itemToResize As FrameworkElement = TryCast(obj, FrameworkElement)
        If (Not itemToResize Is Nothing) Then
            If Object.Equals(e.NewValue, True) Then
                sm_AttachedControls.Add(itemToResize)
                itemToResize.LayoutTransform = New ScaleTransform(sm_CurrentScale, sm_CurrentScale)
            Else
                sm_AttachedControls.Remove(itemToResize)
                itemToResize.LayoutTransform = New ScaleTransform(1, 1)
            End If
        End If
    End Sub

End Class&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;As you can see, there is an attached dependency Boolean property defined with a PropertyChangedCallback. When the PropertyChangedCallback method is called we test to see if it is a True or False value and either add the control to a static list and set the current Transform, or remove the control from the list and reset the transform to 1.&lt;/p&gt;

&lt;p&gt;This works grate and you can manipulate the list of controls at runtime by changing the dependency property.&lt;/p&gt;

&lt;pre class="brush: vb; highlight: [30];"&gt;&amp;lt;igWindows:TabItemEx 
    xmlns:igDP="http://infragistics.com/DataPresenter"     
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:local="clr-namespace:Hinshlabs.WpfHeatItsmDashboard"
    xmlns:igWindows="http://infragistics.com/Windows"
    xmlns:igDock="http://infragistics.com/DockManager"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    mc:Ignorable="d" 
    xmlns:igEditors="http://infragistics.com/Editors"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions" 
    x:Class="CallsView" x:Name="CallsView" MinWidth="30" MinHeight="50"&amp;gt;
    &amp;lt;igWindows:TabItemEx.Resources&amp;gt;
        &amp;lt;local:NinjectDataProvider  
        x:Key="ViewModel" 
        d:IsDataSource="True" ObjectType="{x:Type local:CallsViewModel}"  
        /&amp;gt;
       &amp;lt;local:DateTimeSecondsToBooleanConverter x:Key="DateTimeSecondsToBooleanConverter" /&amp;gt;
    &amp;lt;/igWindows:TabItemEx.Resources&amp;gt;
    &amp;lt;igWindows:TabItemEx.Triggers&amp;gt;
        &amp;lt;EventTrigger RoutedEvent="FrameworkElement.Loaded"/&amp;gt;
    &amp;lt;/igWindows:TabItemEx.Triggers&amp;gt;
    &amp;lt;igWindows:TabItemEx.Header&amp;gt;
        &amp;lt;igEditors:XamTextEditor Text="{Binding Source={StaticResource ViewModel},Path=Header, diag:PresentationTraceSources.TraceLevel=High}" /&amp;gt;
    &amp;lt;/igWindows:TabItemEx.Header&amp;gt;

    &amp;lt;DockPanel local:GlobalScaleTransformBehaviour.IsScaled="True" DataContext="{Binding Source={StaticResource ViewModel}}"&amp;gt;
        &amp;lt;Border DockPanel.Dock="Top" Background="LightGray" MinHeight="20"&amp;gt;
        &amp;lt;Border.Style&amp;gt;
            &amp;lt;Style&amp;gt;
                &amp;lt;Style.Triggers&amp;gt;
                  &amp;lt;DataTrigger Binding="{Binding Source={StaticResource ViewModel},Path=IsLoading, diag:PresentationTraceSources.TraceLevel=High}" Value="False"&amp;gt;
                           &amp;lt;Setter Property="Border.Visibility" Value="Collapsed" /&amp;gt;
                  &amp;lt;/DataTrigger&amp;gt;
                    &amp;lt;/Style.Triggers&amp;gt;
            &amp;lt;/Style&amp;gt;
        &amp;lt;/Border.Style&amp;gt;
            &amp;lt;Label Content="Loading data..." /&amp;gt;
        &amp;lt;/Border&amp;gt;
        &amp;lt;Border DockPanel.Dock="Top" Background="LightGray" MinHeight="20"&amp;gt;
            &amp;lt;Border.Style&amp;gt;
                &amp;lt;Style&amp;gt;
                    &amp;lt;Style.Triggers&amp;gt;
                        &amp;lt;DataTrigger Binding="{Binding Source={StaticResource ViewModel},Path=IsSyncing, diag:PresentationTraceSources.TraceLevel=High}" Value="False"&amp;gt;
                            &amp;lt;Setter Property="Border.Visibility" Value="Collapsed" /&amp;gt;
                        &amp;lt;/DataTrigger&amp;gt;
                    &amp;lt;/Style.Triggers&amp;gt;
                &amp;lt;/Style&amp;gt;
            &amp;lt;/Border.Style&amp;gt;
            &amp;lt;Label Content="Syncing data..." /&amp;gt;
        &amp;lt;/Border&amp;gt;
        &amp;lt;igDP:XamDataGrid DataSource="{Binding Calls}" Theme="Office2k7Blue"&amp;gt;
            &amp;lt;igDP:XamDataGrid.Resources&amp;gt;
                &amp;lt;Style x:Key="{x:Type igDP:DataRecordCellArea}" TargetType="{x:Type igDP:DataRecordCellArea}"&amp;gt;
                &amp;lt;Style.Triggers&amp;gt;
                    &amp;lt;DataTrigger Binding="{Binding DataItem.TypeOfCall, Converter={StaticResource DateTimeSecondsToBooleanConverter}, ConverterParameter=1}" Value="True"&amp;gt;
                            &amp;lt;Setter Property="Background"&amp;gt;
                                &amp;lt;Setter.Value&amp;gt;
                                    &amp;lt;LinearGradientBrush StartPoint="0,0" EndPoint="0,1"&amp;gt;
                                        &amp;lt;LinearGradientBrush.GradientStops&amp;gt;
                                            &amp;lt;GradientStopCollection&amp;gt;
                                                &amp;lt;GradientStop Offset="0" Color="Red"/&amp;gt;
                                                &amp;lt;GradientStop Offset="1" Color="Green"/&amp;gt;
                                            &amp;lt;/GradientStopCollection&amp;gt;
                                        &amp;lt;/LinearGradientBrush.GradientStops&amp;gt;
                                    &amp;lt;/LinearGradientBrush&amp;gt;
                                &amp;lt;/Setter.Value&amp;gt;
                            &amp;lt;/Setter&amp;gt;
                        &amp;lt;/DataTrigger&amp;gt;
                &amp;lt;/Style.Triggers&amp;gt;
            &amp;lt;/Style&amp;gt;
                &amp;lt;/igDP:XamDataGrid.Resources&amp;gt;
            &amp;lt;igDP:XamDataGrid.FieldSettings&amp;gt;
                &amp;lt;igDP:FieldSettings AllowRecordFiltering="true" FilterEvaluationTrigger="OnCellValueChange"  AllowSummaries="True" FilterOperatorDropDownItems="All" /&amp;gt;
            &amp;lt;/igDP:XamDataGrid.FieldSettings&amp;gt;
            &amp;lt;igDP:XamDataGrid.FieldLayoutSettings&amp;gt;
                &amp;lt;igDP:FieldLayoutSettings AutoGenerateFields="true" FilterUIType="LabelIcons" /&amp;gt;
            &amp;lt;/igDP:XamDataGrid.FieldLayoutSettings&amp;gt;
        &amp;lt;/igDP:XamDataGrid&amp;gt;
        &amp;lt;/DockPanel&amp;gt;
&amp;lt;/igWindows:TabItemEx&amp;gt;&lt;/pre&gt;

&lt;p&gt;There is quite a lot of Wpf here, so I have highlighted the DockPanel to which the dependency has been applied. All we now need to do is provide a way to manipulate this value. We need to add a ScaleValue attached dependency property to our Behaviour that we can bind to our single or set of control controls.&lt;/p&gt;

&lt;pre class="brush: vb; highlight: [4,40,41,42,43,44,45,46,48,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,66,67];"&gt;Public Class GlobalScaleTransformBehaviour

    Private Shared sm_AttachedControls As List(Of FrameworkElement)
    Public Shared ReadOnly IsScaledProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsScaled", GetType(Boolean), GetType(GlobalScaleTransformBehaviour), New UIPropertyMetadata(False, New PropertyChangedCallback(AddressOf GlobalScaleTransformBehaviour.IsScaledChanged)))
    Public Shared ReadOnly ScaleValueProperty As DependencyProperty = DependencyProperty.RegisterAttached("ScaleValue", GetType(Double), GetType(GlobalScaleTransformBehaviour), New UIPropertyMetadata(CType(1, Double), New PropertyChangedCallback(AddressOf GlobalScaleTransformBehaviour.ScaleValueChanged)))
    Private Shared sm_CurrentScale As Double = 1

    Shared Sub New()
        sm_AttachedControls = New List(Of FrameworkElement)
    End Sub

    Public Shared Function GetIsScaled(ByVal element As DependencyObject) As Boolean
        If element Is Nothing Then
            Throw New ArgumentNullException("element")
        End If

        Return element.GetValue(IsScaledProperty)
    End Function

    Public Shared Sub SetIsScaled(ByVal element As DependencyObject, ByVal value As Boolean)
        If element Is Nothing Then
            Throw New ArgumentNullException("element")
        End If
        element.SetValue(IsScaledProperty, value)
    End Sub

    Private Shared Sub IsScaledChanged(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        Dim itemToResize As FrameworkElement = TryCast(obj, FrameworkElement)
        If (Not itemToResize Is Nothing) Then
            If Object.Equals(e.NewValue, True) Then
                sm_AttachedControls.Add(itemToResize)
                itemToResize.LayoutTransform = New ScaleTransform(sm_CurrentScale, sm_CurrentScale)
            Else
                sm_AttachedControls.Remove(itemToResize)
                itemToResize.LayoutTransform = New ScaleTransform(1, 1)
            End If
        End If
    End Sub

    Public Shared Function GetScaleValue(ByVal element As DependencyObject) As Double
        If element Is Nothing Then
            Throw New ArgumentNullException("element")
        End If

        Return element.GetValue(ScaleValueProperty)
    End Function

    Public Shared Sub SetScaleValue(ByVal element As DependencyObject, ByVal value As Double)
        If element Is Nothing Then
            Throw New ArgumentNullException("element")
        End If
        element.SetValue(ScaleValueProperty, value)
    End Sub

    Private Shared Sub ScaleValueChanged(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        If Not Application.Current.Dispatcher.CheckAccess Then
            Exit Sub
        End If
        sm_CurrentScale = e.NewValue
        SyncLock sm_AttachedControls
            For Each itemToResize In sm_AttachedControls.ToList
                ' Apply Tensform
                itemToResize.LayoutTransform = New ScaleTransform(sm_CurrentScale, sm_CurrentScale)
            Next
        End SyncLock
    End Sub

End Class&lt;/pre&gt;

&lt;p&gt;This value is stored so we can set new controls, and then applied to all of the currently attached controls. I have chosen to bind to a slider, but any way of passing in the required values is just fine.&lt;/p&gt;

&lt;pre class="brush: vb; highlight: [45];"&gt;&amp;lt;igRibbon:XamRibbonWindow x:Class="MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:igRibbon="http://infragistics.com/Ribbon"
    xmlns:igEditors="http://infragistics.com/Editors"
    xmlns:igWindows="http://infragistics.com/Windows"
    xmlns:igDock="http://infragistics.com/DockManager"
    xmlns:local="clr-namespace:Hinshlabs.WpfHeatItsmDashboard"
    Title="Heat Itsm Dashboard" MinHeight="600" MinWidth="800" Icon="/Hinshlabs.WpfHeatItsmDashboard;component/HeatItsm.ico"&amp;gt;
    &amp;lt;igRibbon:XamRibbonWindow.Resources&amp;gt;
        &amp;lt;local:NinjectDataProvider 
        x:Key="ViewModel" 
        ObjectType="{x:Type local:MainWindowViewModel}" 
        /&amp;gt;
    &amp;lt;/igRibbon:XamRibbonWindow.Resources&amp;gt;
    &amp;lt;igRibbon:RibbonWindowContentHost DataContext="{StaticResource ViewModel}"&amp;gt;
        &amp;lt;igRibbon:RibbonWindowContentHost.Ribbon&amp;gt;
            &amp;lt;igRibbon:XamRibbon local:XamRibbonBehaviour.IsEntryPoint="True" DockPanel.Dock="Top" AutoHideEnabled="True" Theme="Office2k7Blue" &amp;gt;
            &amp;lt;igRibbon:XamRibbon.ApplicationMenu&amp;gt;
                    &amp;lt;igRibbon:ApplicationMenu RecentItemsHeader="{Binding Resources.RecentItemsHeader}" Image="/Hinshlabs.WpfHeatItsmDashboard;component/Images/heat.gif"&amp;gt;
                        &amp;lt;igRibbon:ButtonTool Caption="Update" /&amp;gt;
                    &amp;lt;igRibbon:ApplicationMenu.FooterToolbar&amp;gt;
                        &amp;lt;igRibbon:ApplicationMenuFooterToolbar&amp;gt;
                            &amp;lt;igRibbon:ButtonTool Command="{Binding ExitCommand}" Caption="{Binding Resources.ExitButtonCaption}"/&amp;gt;
                        &amp;lt;/igRibbon:ApplicationMenuFooterToolbar&amp;gt;
                    &amp;lt;/igRibbon:ApplicationMenu.FooterToolbar&amp;gt;
                        &amp;lt;/igRibbon:ApplicationMenu&amp;gt;
                &amp;lt;/igRibbon:XamRibbon.ApplicationMenu&amp;gt;
                &amp;lt;igRibbon:XamRibbon.Tabs&amp;gt;
                    &amp;lt;igRibbon:RibbonTabItem Header="{Binding Resources.Ribbon_HomeTab_Header}"&amp;gt;
                        &amp;lt;igRibbon:RibbonGroup Caption="{Binding Resources.Ribbon_HomeTab_ViewsGroup_Caption}"&amp;gt;
                            &amp;lt;igRibbon:ToolHorizontalWrapPanel&amp;gt;
                                &amp;lt;igRibbon:ButtonTool Caption="{Binding Resources.Ribbon_HomeTab_ViewsGroup_CallsViewButtonCaption}" Command="{Binding AddCallsViewCommand}" /&amp;gt;
                            &amp;lt;/igRibbon:ToolHorizontalWrapPanel&amp;gt;
                        &amp;lt;/igRibbon:RibbonGroup&amp;gt;
                        &amp;lt;igRibbon:RibbonGroup Caption="{Binding Resources.Ribbon_HomeTab_OptionsGroup_Caption}"&amp;gt;
                                    &amp;lt;igRibbon:ToolHorizontalWrapPanel&amp;gt;
                                    &amp;lt;igRibbon:ButtonGroup&amp;gt;
                                        &amp;lt;igRibbon:ToggleButtonTool IsChecked="{Binding FickEnabled, Mode=TwoWay}" Content="{Binding Resources.Ribbon_HomeTab_OptionsGroup_Flick_ToggleButton_Caption}"/&amp;gt;
                                &amp;lt;/igRibbon:ButtonGroup&amp;gt;
                                    &amp;lt;/igRibbon:ToolHorizontalWrapPanel&amp;gt;
                            &amp;lt;igRibbon:ToolHorizontalWrapPanel&amp;gt;
                                &amp;lt;igRibbon:ButtonGroup&amp;gt;
                                    &amp;lt;Label Content="Scale" /&amp;gt;
                                    &amp;lt;Slider Minimum="0.5" Maximum="3" Width="200" local:GlobalScaleTransformBehaviour.ScaleValue="1" LargeChange=".5" SmallChange=".1"  Value="{Binding Path=(local:GlobalScaleTransformBehaviour.ScaleValue),RelativeSource={RelativeSource Self}, Mode=TwoWay}"&amp;gt;
                                    &amp;lt;/Slider&amp;gt;
                                &amp;lt;/igRibbon:ButtonGroup&amp;gt;
                            &amp;lt;/igRibbon:ToolHorizontalWrapPanel&amp;gt;
                        &amp;lt;/igRibbon:RibbonGroup&amp;gt;
                    &amp;lt;/igRibbon:RibbonTabItem&amp;gt;
                &amp;lt;/igRibbon:XamRibbon.Tabs&amp;gt;
            &amp;lt;/igRibbon:XamRibbon&amp;gt;
    &amp;lt;/igRibbon:RibbonWindowContentHost.Ribbon&amp;gt;
        &amp;lt;AdornerDecorator&amp;gt;
        &amp;lt;DockPanel&amp;gt;
            &amp;lt;local:UpdateView DockPanel.Dock="Top" /&amp;gt;
            &amp;lt;igWindows:XamTabControl TabItemCloseButtonVisibility="Visible" TabStripPlacement="Top" ItemsSource="{Binding CallsViews}" SelectedItem="{Binding SelectedCallsView}" local:TabControlTimedBehaviour.IsTimedCycle="{Binding FickEnabled}" Theme="Office2k7Blue"&amp;gt;
            &amp;lt;/igWindows:XamTabControl&amp;gt;
        &amp;lt;/DockPanel&amp;gt;
        &amp;lt;/AdornerDecorator&amp;gt;
    &amp;lt;/igRibbon:RibbonWindowContentHost&amp;gt;
&amp;lt;/igRibbon:XamRibbonWindow&amp;gt;&lt;/pre&gt;
&lt;img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfScaleTransformBehaviour_7143/image_fe341cc8-ae7f-41ce-b7e8-f9d35ee92679.png" width="600" height="450" /&gt; 

&lt;p&gt;As you can see I am heavily utilizing the Infragistics controls, but that would not affect this procedure. The result is the ability to smoothly scale your controls based on a global scale setting.&lt;/p&gt;
&lt;img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfScaleTransformBehaviour_7143/image_f01cf9b5-31a2-435a-b190-97a985fbe245.png" width="600" height="450" /&gt; 

&lt;p&gt; &lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8893cfeb-51e0-4d31-90de-e35e6ecfc1f4" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Behaviours" rel="tag"&gt;Behaviours&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Windows+Presentation+Foundation" rel="tag"&gt;Windows Presentation Foundation&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Infragistics" rel="tag"&gt;Infragistics&lt;/a&gt;&lt;/div&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;krsu46zvpt&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134396"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134396" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/134396.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood (DyslexicDev)</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/08/31/wpf-scale-transform-behaviour.aspx</guid>
            <pubDate>Mon, 31 Aug 2009 07:48:19 GMT</pubDate>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/08/31/wpf-scale-transform-behaviour.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/134396.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/134396.aspx</trackback:ping>
        </item>
        <item>
            <title>Wpf Ninject Dojo: The Data Provider</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/08/25/wpf-ninject-dojo-the-data-provider.aspx</link>
            <description>&lt;p&gt;You have probably heard me go on about Unity a couple of times:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blog.hinshelwood.com/archive/2009/05/08/my.unity.resolveof-ninja.aspx"&gt;My.Unity.Resolve(Of Ninja)&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://blog.hinshelwood.com/archive/2009/05/08/unity-and-asp.net.aspx"&gt;Unity and ASP.NET&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://blog.hinshelwood.com/archive/2009/07/30/creating-a-data-access-layer-using-unity.aspx"&gt;Creating a Data Access layer using Unity&lt;/a&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I have been using what is now &lt;a href="http://www.codeplex.com/unity" rel="tag" target="_blank"&gt;unity&lt;/a&gt; since the good old days (sooo not true, WPF is the Windows Forms killer, and good riddance) of WindowsForms and CAB (Client Application Block), but now there is a lightweight alternative: &lt;a href="http://ninject.org" rel="tag" target="_blank"&gt;Ninject&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;I decided on my latest project (a Wpf dashboard for HEAT ITSM) that I needed dependency injection. Whenever I start building a &lt;a href="http://msdn.microsoft.com/en-us/magazine/dd419663.aspx" rel="tag" target="_blank"&gt;MVVM&lt;/a&gt; project I always end up needing some sort of dependency injection to keep everything nice and neat. It is only really needed once you get to a certain size and when you start wanting talk between &lt;a href="http://en.wikipedia.org/wiki/Model_View_ViewModel" target="_blank"&gt;ViewModels&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Anyway I was using a method of injecting my ViewModels into the Views using standard binding:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;igDock:ContentPane x:Class="SlaTodayView"
    xmlns:igDP="http://infragistics.com/DataPresenter"     
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:local="clr-namespace:WpfHeatItsmDashboard"
    xmlns:igWindows="http://infragistics.com/Windows"
    xmlns:igDock="http://infragistics.com/DockManager"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Header="Sla Today" MinWidth="30" MinHeight="50"&amp;gt;
    &amp;lt;igDock:ContentPane.Resources&amp;gt;
        &amp;lt;ObjectDataProvider 
        x:Key="ViewModel" 
        ObjectType="{x:Type local:SlaTodayViewModel}" 
        /&amp;gt;
    &amp;lt;/igDock:ContentPane.Resources&amp;gt;
    &amp;lt;igDP:XamDataGrid DataContext="{StaticResource ViewModel}" DataSource="{Binding Calls}" Theme="Office2k7Black" &amp;gt;

    &amp;lt;/igDP:XamDataGrid&amp;gt;
&amp;lt;/igDock:ContentPane&amp;gt;&lt;/pre&gt;

&lt;p&gt;But once you move to dependency injection you do not want to keep all those fixed object definitions. These may become interfaces, or you may just want to replace, or dynamically replace, one of these types by a derived one at runtime.&lt;/p&gt;

&lt;p&gt;That being the goal, we need some way to retrieve that type even in design mode. There is nothing worse than components or bits of components that make it difficult to work in both Visual Studio and Blend, and with the new binding features of Visual Studio 2010 for WPF 4 it will be even more important that your usage is as compatible as possible.&lt;/p&gt;

&lt;p&gt;What I decided to do was create a custom &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.data.datasourceprovider.aspx" rel="tag" target="_blank"&gt;DataSourceProvider,&lt;/a&gt; called the NinjectDataProvider that I could use instead of the ObjectDataProvider. This is the first version of that provider and it does nothing more than retrieve the type form the &lt;a href="http://ninject.org" rel="tag" target="_blank"&gt;Ninject&lt;/a&gt; Kernel. Minimal changes to the WPF enable this:&lt;/p&gt;

&lt;pre class="brush: xml; highlight: [10,11,12,13];"&gt;&amp;lt;igDock:ContentPane x:Class="SlaTodayView"
    xmlns:igDP="http://infragistics.com/DataPresenter"     
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:local="clr-namespace:WpfHeatItsmDashboard"
    xmlns:igWindows="http://infragistics.com/Windows"
    xmlns:igDock="http://infragistics.com/DockManager"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Header="Sla Today" MinWidth="30" MinHeight="50"&amp;gt;
    &amp;lt;igDock:ContentPane.Resources&amp;gt;
        &amp;lt;local:NinjectDataProvider  
        x:Key="ViewModel" 
        ObjectType="{x:Type local:SlaTodayViewModel}" 
        /&amp;gt;
    &amp;lt;/igDock:ContentPane.Resources&amp;gt;
    &amp;lt;igDP:XamDataGrid DataContext="{StaticResource ViewModel}" DataSource="{Binding Calls}" Theme="Office2k7Black" &amp;gt;

    &amp;lt;/igDP:XamDataGrid&amp;gt;
&amp;lt;/igDock:ContentPane&amp;gt;&lt;/pre&gt;

&lt;p&gt;As you can see, the only difference is highlighted above and shows the custom &lt;a href="http://msdn.microsoft.com/en-us/library/system.windows.data.datasourceprovider.aspx" rel="tag" target="_blank"&gt;DataSourceProvider&lt;/a&gt; in action.&lt;/p&gt;

&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfNinjectDojoTheDataProvider_C6CF/image_c1d8f10e-3931-49c9-86e1-213ca9fb0d9b.png" width="600" height="507" /&gt;  You can see from the image above that the designer capability is not affected with this actually loading from the database, nice!&lt;/p&gt;

&lt;p&gt;So, what do we need to do to achieve this marvellous result. its actialy fairly simple, I got out my trusty &lt;a href="http://www.red-gate.com/products/reflector/" rel="tag" target="_blank"&gt;reflector&lt;/a&gt; and found that there is really only one method to override.&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Imports System.ComponentModel
Imports System.Threading

Public Class NinjectDataProvider
    Inherits DataSourceProvider

    Private m_objectType As Type

    Public Property ObjectType() As Type
        Get
            Return Me.m_objectType
        End Get
        Set(ByVal value As Type)
            If Not m_objectType Is value Then
                m_objectType = value
                Me.OnPropertyChanged("ObjectType")
                If Not MyBase.IsRefreshDeferred Then
                    MyBase.Refresh()
                End If
            End If
        End Set
    End Property

    Private Overloads Sub OnPropertyChanged(ByVal propertyName As String)
        MyBase.OnPropertyChanged(New PropertyChangedEventArgs(propertyName))
    End Sub

    Protected Overrides Sub BeginQuery()
        If m_objectType Is Nothing Then
            Me.OnQueryFinished(Nothing, New InvalidOperationException("You must provide an ObjectType"), Nothing, Nothing)
        End If
        Dim result As Object
        Try
            result = Application.NinjectKernel.Get(m_objectType)
            Me.OnQueryFinished(result, Nothing, Nothing, Nothing)
        Catch ex As Exception
            Me.OnQueryFinished(Nothing, ex, Nothing, Nothing)
        End Try
    End Sub

End Class&lt;/pre&gt;

&lt;p&gt;I do not yet need all the fancy features of &lt;a href="http://ninject.org" rel="tag" target="_blank"&gt;Ninject&lt;/a&gt; yet so I have only implemented the bit that I need at the moment. If I am adding more (and get it working) I will blog about it in the future.&lt;/p&gt;

&lt;p&gt;To get this working I needed to add an instance of an IKernel object to the “Application” file so I have a single Kernel instance through my application unless I want another, but this is a small price to pay and it could well have been done in the same way as the &lt;a href="http://blog.hinshelwood.com/archive/2009/05/08/my.unity.resolveof-ninja.aspx"&gt;My.Unity.Resolve(Of Ninja)&lt;/a&gt; post I did on &lt;a href="http://www.codeplex.com/unity" rel="tag" target="_blank"&gt;Unity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start your &lt;a href="http://dojo.ninject.org/" target="_blank"&gt;Ninja training&lt;/a&gt; today!&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:90f8b7f8-7124-4031-ac1f-3541ae35526b" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Ninject" rel="tag"&gt;Ninject&lt;/a&gt;,&lt;a href="http://technorati.com/tags/DataSourceProvider" rel="tag"&gt;DataSourceProvider&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ObjectDataProvider" rel="tag"&gt;ObjectDataProvider&lt;/a&gt;,&lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/MVVM" rel="tag"&gt;MVVM&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134306"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134306" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/134306.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood (DyslexicDev)</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/08/25/wpf-ninject-dojo-the-data-provider.aspx</guid>
            <pubDate>Tue, 25 Aug 2009 13:43:35 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/134306.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/08/25/wpf-ninject-dojo-the-data-provider.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/134306.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/134306.aspx</trackback:ping>
        </item>
        <item>
            <title>Silverlight 3</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/08/20/silverlight-3.aspx</link>
            <description>&lt;p&gt;&lt;a href="http://www.amazon.co.uk/gp/product/0470385405?ie=UTF8&amp;amp;tag=dyslexicdev-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0470385405" target="_blank"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 0px 10px 10px 0px; display: inline; border-top: 0px; border-right: 0px" border="0" align="left" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/Silverlight3_CB9C/Silverlight3Wrox_ef0e4f14-7475-4b5d-a88e-b9c8fdbf1d43.jpg" width="128" height="160" /&gt;&lt;/a&gt;&lt;img style="border-bottom-style: none !important; border-right-style: none !important; margin: 0px; border-top-style: none !important; border-left-style: none !important" border="0" alt="" src="http://www.assoc-amazon.co.uk/e/ir?t=marthinssblog-21&amp;amp;l=as2&amp;amp;o=2&amp;amp;a=0470385405" width="1" height="1" /&gt; Over the past week I have been reading the new book &lt;a href="http://www.amazon.co.uk/gp/product/0470385405?ie=UTF8&amp;amp;tag=dyslexicdev-21&amp;amp;linkCode=as2&amp;amp;camp=1634&amp;amp;creative=19450&amp;amp;creativeASIN=0470385405"&gt;Silverlight 3 Programmer's Reference&lt;/a&gt;&lt;img style="border-bottom-style: none !important; border-right-style: none !important; margin: 0px; border-top-style: none !important; border-left-style: none !important" border="0" alt="" src="http://www.assoc-amazon.co.uk/e/ir?t=dyslexicdev-21&amp;amp;l=as2&amp;amp;o=2&amp;amp;a=0470385405" width="1" height="1" /&gt;from Wrox and I have found it one of the best books on Silverlight I have seen in a good while. It is concise without being boring and it provides a wealth of information on Silverlight 3.&lt;/p&gt;  &lt;p&gt;And it is in Colour! I never would have thought that this would make such a difference, I don’t really know why I thought this as I hate looking at code in notepad, but it makes it much easier to read the code pages, both c#/vb and xaml.&lt;/p&gt;  &lt;p&gt;Because I have been using WPF for a number of years this book is perfect for me, although this is a reference book, It has a nice layout that is conducive to both learning and reference.&lt;/p&gt;  &lt;p&gt;Will I be hanging up my WPF hat and replacing it with a Silverlight one? Well, no… but Silverlight 3 is a big step forward…&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:203e2416-2a1d-4bef-b1de-bbbe13c10967" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Silverlight" rel="tag"&gt;Silverlight&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Silvelight+3" rel="tag"&gt;Silvelight 3&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134227"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134227" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/134227.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/08/20/silverlight-3.aspx</guid>
            <pubDate>Thu, 20 Aug 2009 18:50:43 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/134227.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/08/20/silverlight-3.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/134227.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/134227.aspx</trackback:ping>
        </item>
        <item>
            <title>Updating the Command Line Parser</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/08/17/updating-the-command-line-parser.aspx</link>
            <description>&lt;p&gt;I had previously created a Command Line Parser from &lt;a href="http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=7917" target="_blank"&gt;Ray Hayes&lt;/a&gt; codeproject article &lt;a href="http://www.codeproject.com/KB/recipes/commandlineparser.aspx" target="_blank"&gt;Automatic Command Line Parsing in C#&lt;/a&gt;. I had adapted it to VB.NET and upgraded it to .NET 3.5 but I recently ran into the problem with wanting a single command prompt application to handle multiple processes and multiple parameters. This would allow you to group all of a particular tasks commands into a single application. With the advent of Power Shell this format is increasingly less relevant, but with the proliferation of Power Shell many people still prefer to use the good old command line.&lt;/p&gt;  &lt;p&gt;So, staring from the original &lt;a href="http://hinshlabs.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28451" target="_blank"&gt;Command Line Parser v1.0&lt;/a&gt; code I wanted to be able to add multiple commands, or even nest commands. The result is a nice simple commanding architecture conducive to creating multiple commands.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UpdatingtheCommandLineParser_AC5D/image_4.png"&gt;&lt;img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UpdatingtheCommandLineParser_AC5D/image_thumb_1.png" width="600" height="257" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Using this model I can create a simple command…&lt;/p&gt;  &lt;pre class="brush: vb;"&gt;Imports Hinshlabs.CommandLineParser
Imports System.IO
Imports System.Collections.ObjectModel
Imports System.Net

Public Class Demo1Command
    Inherits CommandBase(Of Demo1CommandLine)

    Private m_PortalLocation As Uri

    Public Overrides ReadOnly Property Description() As String
        Get
            Return "demo 1 command demonstrates a sinle nested command"
        End Get
    End Property

    Public Overrides ReadOnly Property Name() As String
        Get
            Return "Demo1"
        End Get
    End Property

    Protected Overrides Function ValidateCommand() As Boolean
        Return True
    End Function

    Public Overrides ReadOnly Property Title() As String
        Get
            Return "demo 1"
        End Get
    End Property

    Public Overrides ReadOnly Property Synopsis() As String
        Get
            Return "demo 1 command"
        End Get
    End Property

    Public Overrides ReadOnly Property Switches() As ReadOnlyCollection(Of SwitchInfo)
        Get
            Return CommandLine.Switches
        End Get
    End Property

    Public Overrides ReadOnly Property Qualifications() As String
        Get
            Return String.Empty
        End Get
    End Property

    Protected Overrides Function RunCommand() As Integer
        Try
            CommandOut.Warning("running Demo1")
            Return -1
        Catch ex As Exception
            CommandOut.Error("Failed: {0}", ex.ToString)
            Return -1
        End Try
    End Function

End Class&lt;/pre&gt;

&lt;p&gt;Or something more substantial:&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Protected Overrides Function RunCommand() As Integer
    Try
        Dim x As New Proxies.MyApp.Configuration.ConfigurationServiceClient("BasicHttpBinding_IConfigurationService", m_PortalLocation.ToString)
        x.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation
        Select Case CommandLine.Action
            Case QuiesceAction.Offline
                x.QuiesceSource(CommandLine.Source, CommandLine.Message, New TimeSpan(0))
            Case QuiesceAction.Online
                x.RestoreSource(CommandLine.Source)
        End Select
        CommandOut.Info("Source {0} has been made {1}", CommandLine.Source, CommandLine.Action.ToString)
        Return 0

    Catch ex As EndpointNotFoundException
        CommandOut.Error("Unable to locate site. Check the value you selected for /Portal:{0}", CommandLine.Portal)
        Return -1
    Catch ex As Exception
        CommandOut.Error("Failed: {0}", ex.ToString)
        Return -1
    End Try
End Function&lt;/pre&gt;

&lt;p&gt;If you are wondering where the variables come from, you can see form Demo1Command that a generic type of Demo1CommandLine is passed in. The application creates an instance of this which wraps the &lt;a href="http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=7917" target="_blank"&gt;Ray Hayes&lt;/a&gt; parser to provide the values from Environment.CommandLine used on the shared methods on the CommandLineBase class.&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;''' &amp;lt;summary&amp;gt;
''' Created a command line object using the Environment.CommandLine information
''' &amp;lt;/summary&amp;gt;
''' &amp;lt;typeparam name="TCommandLine"&amp;gt;The concrete type of object to create&amp;lt;/typeparam&amp;gt;
''' &amp;lt;returns&amp;gt;An instance of the object&amp;lt;/returns&amp;gt;
''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
Public Shared Function CreateCommandLine(Of TCommandLine As {New, CommandLineBase})() As TCommandLine
    Return CreateCommandLine(Of TCommandLine)(Environment.CommandLine)
End Function

''' &amp;lt;summary&amp;gt;
''' Created a command line object using the Environment.CommandLine information
''' &amp;lt;/summary&amp;gt;
''' &amp;lt;typeparam name="TCommandLine"&amp;gt;The concrete type of object to create&amp;lt;/typeparam&amp;gt;
''' &amp;lt;param name="CommandLine"&amp;gt;The command line arguments to parse&amp;lt;/param&amp;gt;
''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
Public Shared Function CreateCommandLine(Of TCommandLine As {New, CommandLineBase})(ByVal CommandLine As String) As TCommandLine
    Dim instance As New TCommandLine
    Dim parser As New Parser(CommandLine, instance)
    parser.Parse()
    instance.Parser = parser
    Return instance
End Function&lt;/pre&gt;

&lt;p&gt;This parser then populates the CommandLine object with values from the CommandLine passed in. For example:&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Imports Hinshlabs.CommandLineParser
Imports System.Collections.ObjectModel

Public Class Demo3CommandLine
    Inherits CommandLineBase

    Private m_value1 As String
    Private m_value2 As Value2Values = Value2Values.Value1

    &amp;lt;CommandLineSwitch("Value1", "Adds a string value named value1"), CommandLineAlias("v1")&amp;gt; _
    Public Property Value1() As String
        Get
            Return Me.m_value1
        End Get
        Set(ByVal value As String)
            Me.m_value1 = value
        End Set
    End Property

    &amp;lt;CommandLineSwitch("Value2", "Adds and enum value called value2"), CommandLineAlias("v2")&amp;gt; _
    Public Property Value2() As Value2Values
        Get
            Return Me.m_value2
        End Get
        Set(ByVal value As Value2Values)
            Me.m_value2 = value
        End Set
    End Property

    Public Enum Value2Values
        Enum1
        Enum2
        Enum3
    End Enum

End Class&lt;/pre&gt;

&lt;p&gt;Would allow you to call [consoleApp] Demo3 /v1:”Any value you like” /Value2:Enum3 and have the correct values populated at runtime.&lt;/p&gt;

&lt;p&gt;I have also updated with a DelegateCommand class that would allow you to call a function in the right format from anywhere:&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;New DelegateCommand(Of Demo3CommandLine)("Demo2", AddressOf OnDemo2Run, "demo 2", "no additional information", "demo 2 command", "This command shows how to delegate the run method using the delegate command")&lt;/pre&gt;

&lt;p&gt;The delegate command is really easy in .NET 3.5 with the only change being the addition of a variable declared as a Func in the class:&lt;/p&gt;

&lt;pre class="brush: vb; highlight: [14,28,29,30,31,32,33,34,35,65,67];"&gt;Imports Hinshlabs.CommandLineParser
Imports System.IO
Imports System.Collections.ObjectModel
Imports System.Net

Public Class DelegateCommand(Of TCommandLine As {New, CommandLineBase})
    Inherits CommandBase(Of TCommandLine)

    Private m_Description As String
    Private m_Title As String
    Private m_Synopsis As String
    Private m_Qualifications As String
    Private m_name As String
    Private m_RunCommand As Func(Of Integer)

    Public Overrides ReadOnly Property Description() As String
        Get
            Return m_Description
        End Get
    End Property

    Public Overrides ReadOnly Property Name() As String
        Get
            Return m_name
        End Get
    End Property

    Protected Overrides Function RunCommand() As Integer
        Try
            Return m_RunCommand.Invoke
        Catch ex As Exception
            CommandOut.Error("Failed: {0}", ex.ToString)
            Return -1
        End Try
    End Function

    Protected Overrides Function ValidateCommand() As Boolean
        Return True
    End Function

    Public Overrides ReadOnly Property Title() As String
        Get
            Return m_title
        End Get
    End Property

    Public Overrides ReadOnly Property Synopsis() As String
        Get
            Return Synopsis 
        End Get
    End Property

    Public Overrides ReadOnly Property Switches() As ReadOnlyCollection(Of SwitchInfo)
        Get
            Return CommandLine.Switches
        End Get
    End Property

    Public Overrides ReadOnly Property Qualifications() As String
        Get
            Return String.Empty
        End Get
    End Property

    Public Sub New(ByVal name As String, ByVal runCommand As Func(Of Integer), ByVal title As String, ByVal qualifications As String, ByVal synopsis As String, ByVal description As String)
        m_name = name
        m_RunCommand = runCommand
        m_Title = title
        m_Qualifications = qualifications
        m_Synopsis = synopsis
        m_Description = description
    End Sub

End Class&lt;/pre&gt;

&lt;p&gt;If you were wondering why there are so many properties, it is to allow the help to be created automatically. For example if you call the help function on Demo3Command you will get…&lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UpdatingtheCommandLineParser_AC5D/image_2fd1f26f-de28-4c9a-a746-edf9887615a4.png" width="628" height="158" /&gt; &lt;/p&gt;

&lt;p&gt;With the values coming from the relevant places:&lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UpdatingtheCommandLineParser_AC5D/image_422c0996-339e-4054-835a-dc29f41a7433.png" width="618" height="162" /&gt; &lt;/p&gt;

&lt;p&gt;It will also support inherited CommandLine objects to minimize duplication.&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;I hope that if you are building command line apps that you will have a look, just remember not to spend too much effort on cmd, when Power Shell is much more suitable and accessible to non developers.&lt;/p&gt;

&lt;p&gt;Get &lt;a href="http://hinshlabs.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31651" rel="tag" target="_blank"&gt;Command Line Parser v2.0&lt;/a&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:09961db3-ed87-47a9-ab1b-4d09bcc58d9d" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/VB.NET" rel="tag"&gt;VB.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/CommandLine" rel="tag"&gt;CommandLine&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134142"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134142" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/134142.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood (DyslexicDev)</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/08/17/updating-the-command-line-parser.aspx</guid>
            <pubDate>Mon, 17 Aug 2009 00:11:08 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/134142.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/08/17/updating-the-command-line-parser.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/134142.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/134142.aspx</trackback:ping>
        </item>
        <item>
            <title>Wpf Drag &amp;amp; Drop behaviour</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/08/14/wpf-drag-amp-drop-behaviour.aspx</link>
            <description>&lt;p&gt;A colleague of mine was having a bit of trouble getting drag and drop working in a way that fitted well with the MVVM pattern. This is really quite simple once you have a certain level of understanding of Patterns, but is a complete nightmare if you do not.&lt;/p&gt;  &lt;p&gt;One of the founding principals of MVVM is that you should never be writing code in your code behind, it should all be encapsulated away and be bindable in XAML to achieve the result. Anyone who has tackled drag and drip will have suddenly found their code behind covered in code for handling both the drag and the drop, and multiplied up when dealing with multiple controls.&lt;/p&gt;  &lt;p&gt;I cruised the web for information, of which I found plenty and settled on an example by &lt;a title="Bea Stollnitz on Silverlight and WPF" href="http://www.beacosta.com" rel="tag" target="_blank"&gt;Bea Stollnitz&lt;/a&gt; of Microsoft. In her &lt;a title="How can I drag and drop items between data bound ItemsControls?" href="http://www.beacosta.com/blog/?p=53" rel="tag" target="_blank"&gt;post&lt;/a&gt; i had found one of the best and most intuitive examples of the Drag &amp;amp; Drop Behaviour written in C#.&lt;/p&gt;  &lt;p&gt;I am not going to go into all of her code which she has available for download, just to say that it is nice, and is exactly what I am looking for even with the limitations that she described.&lt;/p&gt;  &lt;p&gt;The functionality available allows you to drag a piece of data from one ItemsControl to another of the same data type or to reorder within itself. It provides for a floating template for the dragging item and a visual cue for the drop location.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="InsertionAdorner" border="0" alt="InsertionAdorner" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfDragDropbehaviour_E187/InsertionAdorner_3.png" width="773" height="464" /&gt; &lt;/p&gt;  &lt;p&gt;I wanted to augment this to allow for other scenarios while keeping as much functionality as possible.&lt;/p&gt;  &lt;p&gt;Likes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Drag functionality&lt;/li&gt;    &lt;li&gt;Drag templating – nice!&lt;/li&gt;    &lt;li&gt;Encapsulation of logic&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Dislikes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;No way to control drop behaviour&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;My version lets you inject additional functionality at runtime. The adjusted class diagram shows the relationships, but we only really use the DragDropBehaviour class&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfDragDropbehaviour_E187/image_8.png" width="500" height="434" /&gt; &lt;/p&gt;  &lt;p&gt;You can still use the standard options:&lt;/p&gt;  &lt;pre class="brush: xml;"&gt;&amp;lt;DockPanel&amp;gt;
    &amp;lt;Label DockPanel.Dock="Top"  Content="Checkout" /&amp;gt;
    &amp;lt;ListBox     hlb:DragDropBehaviour.IsDragSource="true" 
                 hlb:DragDropBehaviour.IsDropTarget="true" 
                 hlb:DragDropBehaviour.DragTemplate="{StaticResource MyTemplate}" 
                 ItemsSource="{Binding Items}" 
                 MinWidth="100" 
                 MinHeight="100" 
                 AllowDrop="True" 
                 SelectionMode="Multiple"&amp;gt;
    &amp;lt;/ListBox&amp;gt;
&amp;lt;/DockPanel&amp;gt;&lt;/pre&gt;

&lt;p&gt;But I have added another bindable option of DropProcessor that allows you to override the default DropProcessor to achieve whatever you want.&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;ListBox hlb:DragDropBehaviour.DropProcessor="{Binding DropProcessor}" 
    hlb:DragDropBehaviour.IsDragSource="true" 
    hlb:DragDropBehaviour.IsDropTarget="true" 
    hlb:DragDropBehaviour.DragTemplate="{StaticResource moo}" 
    ItemsSource="{Binding Items}" 
    MinWidth="100" 
    MinHeight="100"&amp;gt;&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;In this example I have created a little gun shop called “Nutters R’ Us” where you can buy weapons and ordinance. You can see that there is an area for weapons, and area for ordinance and an area for your selected purchases.&lt;/p&gt;

&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfDragDropbehaviour_E187/image_7.png" width="390" height="293" /&gt; &lt;/p&gt;

&lt;p&gt;I have added a custom DropProcessor only to the Checkout area that only applies when you drop items of type “OrdinanceViewModel”&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Public Class CheckoutDropProcessor
    Inherits DropProcessor

    Public Overrides Function GetDropAdorner(ByVal behaviour As DragDropBehaviour, ByVal adornerLayer As System.Windows.Documents.AdornerLayer) As DropAdorner
        If TypeOf behaviour.TargetItemContainer.DataContext Is WeaponViewModel Then
            If TypeOf behaviour.SourceItemContainer.DataContext Is OrdnanceViewModel Then
                Return New OrdnanceToWeaponDropAdorner(behaviour, adornerLayer)
            End If
        End If
        Return MyBase.GetDropAdorner(behaviour, adornerLayer)
    End Function

    Public Overrides Function IsDropAllowed(ByVal behaviour As DragDropBehaviour, ByVal draggedItem As Object) As Boolean
        If Not behaviour.SourceItemContainer Is Nothing AndAlso TypeOf behaviour.SourceItemContainer.DataContext Is OrdnanceViewModel Then
            If Not behaviour.TargetItemContainer Is Nothing AndAlso TypeOf behaviour.TargetItemContainer.DataContext Is WeaponViewModel Then
                Return True
            End If
            Return False
        End If
        Return MyBase.IsDropAllowed(behaviour, draggedItem)
    End Function

    Public Overrides Sub Drop(ByVal behaviour As DragDropBehaviour, ByVal draggedItem As Object, ByVal dropEffect As System.Windows.DragDropEffects)
        If Not behaviour.TargetItemContainer Is Nothing AndAlso TypeOf behaviour.TargetItemContainer.DataContext Is WeaponViewModel Then
            If TypeOf behaviour.SourceItemContainer.DataContext Is OrdnanceViewModel Then
                CType(behaviour.TargetItemContainer.DataContext, WeaponViewModel).AddOrdinance(CType(behaviour.SourceItemContainer.DataContext, OrdnanceViewModel))
                Dim indexRemoved As Integer = -1
                If ((dropEffect And DragDropEffects.Move) &amp;lt;&amp;gt; DragDropEffects.None) Then
                    indexRemoved = Utilities.RemoveItemFromItemsControl(behaviour.SourceItemsControl, draggedItem)
                End If
                If (((indexRemoved &amp;lt;&amp;gt; -1) AndAlso (behaviour.SourceItemsControl Is behaviour.TargetItemsControl)) AndAlso (indexRemoved &amp;lt; behaviour.InsertionIndex)) Then
                    behaviour.InsertionIndex -= 1
                End If
                Exit Sub
            End If
        End If
        MyBase.Drop(behaviour, draggedItem, dropEffect)

    End Sub

End Class&lt;/pre&gt;

&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfDragDropbehaviour_E187/image_11.png" width="440" height="236" /&gt; &lt;/p&gt;

&lt;p&gt;This class inherits from the base class “DropProcessor” that provides the same functionality as the original article, but I have &lt;/p&gt;

&lt;p&gt;overridden couple of methods. The first, “GetDropAdorner” test to make sure that you are dropping a OrdinanceViewModel onto a WeaponViewModel and provides a different and custom DropAdorner that instead of providing the lovely insertion visual it just applied a “IsDropTarget” property to the ListBoxItem to allow a template to control the visual. The IsAllowedDrop also test for this case, as does the Drop method. In all cases they are just testing for a special case of Drop and call the base classes methods.&lt;/p&gt;

&lt;p&gt;The diagram for the demo app is a little large, but you can see how much I still suck at MVVM, and although I have learned a lot doing this demo, I am still tempted to share ViewModels… but that is a bad habit.&lt;/p&gt;

&lt;p&gt; &lt;img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/WpfDragDropbehaviour_E187/image_4a27137a-a443-45ba-b866-2c3b2f2dbdf5.png" width="600" height="874" /&gt; &lt;/p&gt;

&lt;p&gt;I have highlighted the two main classes, and we have already discussed the CheckoutDropProcessor. This allows you the flexibility to augment your drop scenarios without all of your developers having to get too deep in the guts on the behaviour, thus leaving them plenty of time for the real work of actually building something useful.&lt;/p&gt;

&lt;p&gt;I have put this &lt;a href="http://hinshlabs.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31504" target="_blank"&gt;up on Codeplex&lt;/a&gt;, and both the &lt;a href="http://hinshlabs.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31504#DownloadId=79055" target="_blank"&gt;source&lt;/a&gt; and &lt;a href="http://hinshlabs.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=31504#DownloadId=79056" target="_blank"&gt;binaries&lt;/a&gt; are available.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8e79d278-1e00-4f12-8f48-b7e7a5cd8328" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/WPF" rel="tag"&gt;WPF&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Behaviour" rel="tag"&gt;Behaviour&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Adorner" rel="tag"&gt;Adorner&lt;/a&gt;,&lt;a href="http://technorati.com/tags/MVVM" rel="tag"&gt;MVVM&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134103"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=134103" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/134103.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/08/14/wpf-drag-amp-drop-behaviour.aspx</guid>
            <pubDate>Fri, 14 Aug 2009 03:16:04 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/134103.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/08/14/wpf-drag-amp-drop-behaviour.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/134103.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/134103.aspx</trackback:ping>
        </item>
        <item>
            <title>Creating a Data Access layer using Unity</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/07/30/creating-a-data-access-layer-using-unity.aspx</link>
            <description>&lt;p&gt;I am always pulling out the Unity assemblies. Maybe it is just because I am lazy, but I really can’t be bothered rolling my own dependency injection and mapping framework!&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/CreatingaDataAccesslayerusingUnity_E289/image_13.png" width="240" height="261" /&gt;&lt;/p&gt;  &lt;p&gt;I am going to use Unity only as a mapping frame work for now, I want to be able to pass an Interface into a method, and get back the correct data access class.&lt;/p&gt;  &lt;p&gt;The plan is to meet the diagram on the left. Only the factory and the interfaces are accessible, but are all set to “friend” which will require an assembly tag to be added to both the Factory and the Interfaces assemblies to allow explicit access.&lt;/p&gt;  &lt;pre class="brush: vb;"&gt;&amp;lt;Assembly: InternalsVisibleTo("Hinshlabs.TfsDynamicPolicy.Services.Server")&amp;gt; &lt;/pre&gt;

&lt;p&gt;This allows classes in the named assembly to access all classes and methods that have been prefaced with the “Friend” access level. Its a sneaky way of helping to maintain your layer integrity. So with this reference added only the Services.Server assembly, the one with the web service implementation, can access the factory and the interfaces, making them un-callable from any other assembly.&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff0000" size="1"&gt;note: if you use only the assembly’s friendly name and not the explicit signed name then someone could just create an assembly of the same name as above and they will be able to call as if they were Services.Server. This is not to prevent hacking, just those pesky developers (me) who may try to bypass the service tier…&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;If, like me you are running tests you will also need to add an InternalsVisibleTo entry for your test assemblies or you will be plagued by “Assessors”..&lt;/p&gt;

&lt;p&gt;First is my IDataAccess class, this is really only exists so there is some validation on my generics.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/CreatingaDataAccesslayerusingUnity_E289/image34.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/CreatingaDataAccesslayerusingUnity_E289/image34_thumb.png" width="146" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;pre class="brush: vb; "&gt;' Assembly: Hinshlabs.TfsDynamicPolicy.DataAccess.Common
Public Interface IDataAccess

End Interface&lt;/pre&gt;

&lt;p&gt;I also have a more specific Interface that allows for the loading of Artefacts. I have not yet implemented anything more than get and add, but you can see that it inherits (yes an interface and inherits in the same sentence) from the IDataAccess interface so we can pass it as a generic type that complies with IDataAccess.&lt;/p&gt;

&lt;pre class="brush: vb; "&gt;'Assembly: Hinshlabs.TfsDynamicPolicy.DataAccess.Common 
Imports Hinshlabs.TfsDynamicPolicy.Common

Public Interface IArtifactDataAccess(Of T As Artifact)
    Inherits IDataAccess

    Function GetArtifact(ByVal id As Guid) As T
    Function GetArtifact(ByVal Uri As Uri) As T
    Function GetArtifacts() As ArtifactCollection
    Function AddArtifact(ByVal artifact As T) As Boolean

End Interface&lt;/pre&gt;

&lt;p&gt;Wow… that was hard, IDataAccess may have a little more than nothing in the future, but for now that is it. Now, what I need is a class that I can inherit from that will provide the functionality I need for any factory. This is mainly coz factories bread factories. &lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/CreatingaDataAccesslayerusingUnity_E289/image25.png" width="182" height="300" /&gt;&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;'Assembly: Hinshlabs.TfsDynamicPolicy.Common
Imports System.IO
Imports System.Globalization
Imports System.Xml.Serialization
Imports System.Configuration
Imports Microsoft.Practices.Unity
Imports Microsoft.Practices.Unity.Configuration
Imports Hinshlabs.TfsDynamicPolicy.Common
Imports System.Reflection

Friend MustInherit Class UnityFactoryBase(Of T As {New, UnityFactoryBase(Of T)})

#Region " Singleton"

    Private Shared m_Instance As T

    Friend Shared ReadOnly Property Instance As T
        Get
            If m_Instance Is Nothing Then
                m_Instance = New T
                m_Instance.Initialize()
            End If
            Return m_Instance
        End Get
    End Property

    Protected Sub New()
        ' Do nothing in here
    End Sub

#End Region

    Private m_UnityContainer As IUnityContainer

    Private Sub Initialize()
        ' Create Unity container
        m_UnityContainer = New UnityContainer()
        ' Configure Unity
        Dim config As Configuration
        Dim fm As New ExeConfigurationFileMap

        fm.ExeConfigFilename = ConfigFilename
        Dim configFileLocation As String = Path.Combine(Path.GetDirectoryName(Assembly.GetCallingAssembly.Location), ConfigFilename)
        If Not File.Exists(configFileLocation) Then
            Throw New FileNotFoundException(String.Format(CultureInfo.InvariantCulture, "Unable to load config file with the name {0}", fm.ExeConfigFilename), configFileLocation)
        End If
        config = ConfigurationManager.OpenMappedExeConfiguration(fm, ConfigurationUserLevel.None)
        Dim section As UnityConfigurationSection = CType(config.GetSection("unity"), UnityConfigurationSection)
        If section Is Nothing Then
            Throw New AccessViolationException(String.Format(CultureInfo.InvariantCulture, "There is no unity section called {0} in the config file {1}", UnityContainerName, ConfigFilename))
        End If
        section.Containers(UnityContainerName).Configure(m_UnityContainer)
    End Sub

    Protected ReadOnly Property UnityContainer As IUnityContainer
        Get
            Return m_UnityContainer
        End Get
    End Property

    Protected MustOverride ReadOnly Property UnityContainerName As String
    Protected MustOverride ReadOnly Property ConfigFilename As String

End Class&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;The UnityFactoryBase class provides a couple of features. It provides a Singleton pattern so that we make sure that there is only ever one instance per factory type T and we initialise a UnityContainer for each Instance of factory T. You can see that on the class definition the generic type T that will be passed in is of the same type as the class itself. This makes sure that the class that represents T inherits from UnityFactoryBase(Of T As {New, UnityFactoryBase(Of T)}). When configuring the Unity Container we get both the container name and the config file to load from the child class. This allows for both different config files per factory and the option to have a single config file and multiple unity configuration elements. Its up to you…&lt;/p&gt;

&lt;p&gt;We need to inherit from UnityFactoryBase(Of T As {New, UnityFactoryBase(Of T)})  to create our factory and provide a config file to configure the UnityContainer. The inherited class is pretty simple as we have done most of the heavy lifting in the base class.&lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 10px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/CreatingaDataAccesslayerusingUnity_E289/image19.png" width="260" height="237" /&gt;&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Imports Hinshlabs.TfsDynamicPolicy.DataAccess.Common
' Assembly: Hinshlabs.TfsDynamicPolicy.DataAccess
Imports Hinshlabs.TfsDynamicPolicy.Common
Imports System.Globalization

Friend Class DataAccessFactory
    Inherits UnityFactoryBase(Of DataAccessFactory)

    Public Sub New()
        ' Do nothing in here
    End Sub

    Protected Overrides ReadOnly Property UnityContainerName As String
        Get
            Return "DataAccess"
        End Get
    End Property

    Protected Overrides ReadOnly Property ConfigFilename As String
        Get
            Return String.Format(CultureInfo.InvariantCulture, "{0}.Unity.config", System.Reflection.Assembly.GetExecutingAssembly().GetName.Name)
        End Get
    End Property

    Public Function GetDataAccess(Of T As IDataAccess)() As T
        Return UnityContainer.Resolve(Of T)()
    End Function

End Class&lt;/pre&gt;

&lt;p style="clear: both"&gt; &lt;/p&gt;

&lt;p&gt;The DataAccessFactory provides the data needed by the UnityFactoryBase(Of DataAccessFactory) as well as the method that I need to retrieve an IDataAccess class. I will show you how it is called, but first there is the little matter of config:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;
&amp;lt;configuration&amp;gt;
  &amp;lt;configSections&amp;gt;
    &amp;lt;section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /&amp;gt;
  &amp;lt;/configSections&amp;gt;
  &amp;lt;unity&amp;gt;
    &amp;lt;typeAliases&amp;gt;
      &amp;lt;!-- Lifetime manager types should be inserted if you need lifetime managers --&amp;gt;
      &amp;lt;typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" /&amp;gt;
      &amp;lt;typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" /&amp;gt;
      &amp;lt;!-- User defined type aliases --&amp;gt;
      &amp;lt;!-- An interface for artifact data access implementation --&amp;gt;
      &amp;lt;typeAlias alias="IArtifactDataAccess`1" type="Hinshlabs.TfsDynamicPolicy.DataAccess.Common.IArtifactDataAccess`1, Hinshlabs.TfsDynamicPolicy.DataAccess.Common" /&amp;gt;
    &amp;lt;/typeAliases&amp;gt;
    &amp;lt;containers&amp;gt;
      &amp;lt;container name="DataAccess"&amp;gt;
        &amp;lt;types&amp;gt;
          &amp;lt;!-- Lifetime managers specified using the type aliases --&amp;gt;
          &amp;lt;type type="IArtifactDataAccess`1" mapTo="Hinshlabs.TfsDynamicPolicy.DataAccess.Xml.ArtifactDataAccess`1, Hinshlabs.TfsDynamicPolicy.DataAccess.Xml"&amp;gt;
            &amp;lt;lifetime type="singleton" /&amp;gt;
          &amp;lt;/type&amp;gt;
        &amp;lt;/types&amp;gt;
      &amp;lt;/container&amp;gt;
    &amp;lt;/containers&amp;gt;
  &amp;lt;/unity&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/pre&gt;

&lt;p&gt;I am not going to explain the config file as it is well (ish) documented, but it effectively mapped all generic calls to retrieve IArtifactDataAccess`1 to the implementation in the XML assembly of ArtifactDataAccess`1 and makes the resultant object a singleton.&lt;/p&gt;

&lt;p&gt;To call this lovely package after you have populated it with many many DataAccess goodies all you need to do is this:&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Dim dal As IArtifactDataAccess(Of DynamicPolicy) = DataAccessFactory.Instance.GetDataAccess(Of IArtifactDataAccess(Of DynamicPolicy))()&lt;/pre&gt;

&lt;p&gt;Lovely and simple, and to add a new implementation all I need is an Interface like IArtifactDataAccess.. lets call it IHypotheticalDataBits, a concrete implementation… lets call it HypoDataFromTwitter and a mapping in the config file:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;type type="IHypotheticalDataBits" mapTo="Hinshlabs.TfsDynamicPolicy.DataAccess.Xml.HypoDataFromTwitter, Hinshlabs.TfsDynamicPolicy.DataAccess.Xml"&amp;gt;
  &amp;lt;lifetime type="singleton" /&amp;gt;
&amp;lt;/type&amp;gt;&lt;/pre&gt;

&lt;p&gt;And you can then call:&lt;/p&gt;

&lt;pre class="brush: vb; "&gt;Dim dal As IHypotheticalDataBits = DataAccessFactory.Instance.GetDataAccess(Of IHypotheticalDataBits)()&lt;/pre&gt;

&lt;p&gt; &lt;/p&gt;

&lt;p&gt;Any easier and it would be writing for you :)&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:d33531d7-f87c-4394-8457-4474ff5d3715" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/VB.NET" rel="tag"&gt;VB.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Generics" rel="tag"&gt;Generics&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Factory+Pattern" rel="tag"&gt;Factory Pattern&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Singleton+pattern" rel="tag"&gt;Singleton pattern&lt;/a&gt;,&lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Unity+Application+Block" rel="tag"&gt;Unity Application Block&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Unity" rel="tag"&gt;Unity&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133817"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133817" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/133817.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/07/30/creating-a-data-access-layer-using-unity.aspx</guid>
            <pubDate>Thu, 30 Jul 2009 03:57:53 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/133817.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/07/30/creating-a-data-access-layer-using-unity.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/133817.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/133817.aspx</trackback:ping>
        </item>
        <item>
            <title>Log Elmah errors in Team Foundation Server</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/07/26/log-elmah-errors-in-team-foundation-server.aspx</link>
            <description>&lt;p&gt;I am not sure if this is a good idea, but I was bored one day and decided to add a TFS Error Log provider for &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt;. There are 2 ways you can do this. You can create a new WorkItem type and log an error report for each of the errors or you can create one work item for each error type/title. To do this you can create a title that is the combination of error message and application name and then search TFS for an existing work item. If it exists then add the error to it, if it does not then create a work item for that instance. You can use any work item type, and the errors are added as &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt; xml log files. &lt;/p&gt;  &lt;p&gt;There are a number of things you need to override when you inherit from &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt;.ErrorLog. The first is the Log method.&lt;/p&gt;  &lt;pre class="brush: vb;"&gt;''' &amp;lt;summary&amp;gt;
''' Logs the error as an attachment to an existing work item, or adds a new work item if this error has not occurred.
''' &amp;lt;/summary&amp;gt;
''' &amp;lt;param name="error"&amp;gt;The error to be logged&amp;lt;/param&amp;gt;
''' &amp;lt;returns&amp;gt;The ID of the error&amp;lt;/returns&amp;gt;
''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
Public Overrides Function Log(ByVal [error] As [Error]) As String
    Dim errorId = Guid.NewGuid().ToString()
    Dim timeStamp = DateTime.UtcNow.ToString("yyyy-MM-ddHHmmssZ", CultureInfo.InvariantCulture)
    Dim Filename = String.Format("error-{0}-{1}.elmah", timeStamp, errorId)
    Dim temp = System.IO.Path.Combine(".", Filename)
    ' Temp Log to disk
    Using writer = New XmlTextWriter(temp, Encoding.UTF8)
        writer.Formatting = Formatting.Indented
        writer.WriteStartElement("error")
        writer.WriteAttributeString("errorId", errorId)
        ErrorXml.Encode([error], writer)
        writer.WriteEndElement()
        writer.Flush()
    End Using

    Dim Title As String = String.Format("{0}-{1}", [error].ApplicationName, [error].Message)

    Dim wi As WorkItem = GetWorkItemForException(Title, [error])

    Dim a As New Attachment(temp, "Elmah error log")

    wi.Attachments.Add(a)
    If wi.IsValid Then
        wi.Save()
        Return String.Format("{0}|{1}", wi.Id, errorId.ToString)
    Else
        Dim message As New System.Text.StringBuilder
        Dim results = wi.Validate()
        Dim isFirst As Boolean = True
        For Each r In results
            message.AppendLine(String.Format(IIf(isFirst, "{0}", ", {0}"), r))
            isFirst = False
        Next
        Throw New ApplicationException(String.Format("Unable to save the work item because the following fields produced a validation error '{0}'.", message.ToString))
    End If
End Function&lt;/pre&gt;

&lt;p&gt;The idea is that you attach the &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt; log file to the work item with a .&lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;elmah&lt;/a&gt; extension. This will allow us to find all the error logs in the future. So we create the temporary log file, and then create our key/title for our work item. You can customize this by customizing your exception messages on the server side. We then get our work item, and add the file as an attachment.&lt;/p&gt;

&lt;p&gt;Because I am doing this the quick and dirty way, i.e. just for fun, I have utilised the API’s provided in the Templates add-on for the Power Tools to customize the work items. So when we are creating the Work item:&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Protected Function GetWorkItemForException(ByVal Title As String, ByVal [error] As [Error]) As WorkItem
    Dim wi As WorkItem = GetExistingWorkItem(Title)
    If wi Is Nothing Then
        wi = CreateNewWorkItem(Title)
    End If
    m_TemplateDefault.Fields.ApplyFieldValues(wi, False)
    ApplyErrorFieldValues(wi, [error])
    Return wi
End Function&lt;/pre&gt;

&lt;p&gt;So, we either get an existing work item, or we create a new one, but then we need to apply some values to the work item. In the constructor of the class &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt; passes an IDictionary object that we use to pass the template names.&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Public Sub New(ByVal config As IDictionary)
    If config Is Nothing Then
        Throw New ArgumentNullException("config")
    End If
    sm_Config = config

    Dim store As ITemplateStore = GetStore()
    m_TemplateDefault = GetTemplate("Defaults", store)
    m_TemplateErrorMap = GetTemplate("ErrorMap", store)

    If m_TemplateDefault Is Nothing Or m_TemplateErrorMap Is Nothing Then
        Throw New ApplicationException("Unable to load the templates from the store.")
    End If

End Sub&lt;/pre&gt;

&lt;p&gt;I created a Store (Microsoft.TeamFoundation.PowerTools.Client.WorkItemTracking.Templates.ITemplateStore) for the templates and attempt to load both a “defaults” template and a dynamic “mapping” template. The latter will need some special mapping, but as you can see from the GetWorkItemForException there is already a method on the Template object to Apply all of the values to a work item. Here is an example default template:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;Template xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&amp;gt;
  &amp;lt;FieldValues&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;System.AreaPath&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;TestProject1\TestArea1&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;System.IterationPath&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;TestProject1\TestIteration1&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;System.AssignedTo&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;Martin Hinshelwood&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;Microsoft.VSTS.CMMI.FoundInEnvironment&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;DEV&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;Microsoft.VSTS.Build.FoundIn&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;Build_v1.13_20090312.1&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
  &amp;lt;/FieldValues&amp;gt;
  &amp;lt;WorkItemTypeName&amp;gt;Bug&amp;lt;/WorkItemTypeName&amp;gt;
  &amp;lt;TeamServerUri&amp;gt;http://tfs01.company.biz:8080/&amp;lt;/TeamServerUri&amp;gt;
  &amp;lt;TeamProjectName&amp;gt;TestProject1&amp;lt;/TeamProjectName&amp;gt;
  &amp;lt;Description /&amp;gt;
&amp;lt;/Template&amp;gt;&lt;/pre&gt;

&lt;p&gt;These values are now mapped onto the work item. But what about any dynamic values that we want to use from the Error. I added a second template called “ErrorMap” that will use the same format, but use something like:&lt;/p&gt;

&lt;pre class="brush: xml;"&gt;&amp;lt;?xml version="1.0"?&amp;gt;
&amp;lt;Template xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&amp;gt;
  &amp;lt;FieldValues&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;System.AreaPath&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;TestProject1\{ApplicationName}&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;System.Description&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;{WebHostHtmlMessage}&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
    &amp;lt;FieldValue&amp;gt;
      &amp;lt;ReferenceName&amp;gt;Company.Custom.MethodName&amp;lt;/ReferenceName&amp;gt;
      &amp;lt;Value&amp;gt;{Exception.TargetSite.Name}&amp;lt;/Value&amp;gt;
    &amp;lt;/FieldValue&amp;gt;
  &amp;lt;/FieldValues&amp;gt;
  &amp;lt;WorkItemTypeName&amp;gt;Bug&amp;lt;/WorkItemTypeName&amp;gt;
  &amp;lt;TeamServerUri&amp;gt;http://tfs01.company.biz:8080/&amp;lt;/TeamServerUri&amp;gt;
  &amp;lt;TeamProjectName&amp;gt;TestProject1&amp;lt;/TeamProjectName&amp;gt;
  &amp;lt;Description /&amp;gt;
&amp;lt;/Template&amp;gt;&lt;/pre&gt;

&lt;p&gt;We can then apply those values with a little reflection by parsing out the value and applying the retrieved object values to the work item.&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Private Sub ApplyErrorFieldValues(ByVal wi As WorkItem, ByVal [error] As [Error])
    For Each i In m_TemplateErrorMap.Fields
        Dim value As String = GetPropertyValue(i.Value, [error])
        If wi.Fields(i.ReferenceName).AllowedValues.Contains(value) Then
            wi.Fields(i.ReferenceName).Value = value
        Else
            Throw New ApplicationException(String.Format("Unable to set the work item field '{0}' to '{1}' as '{1}' is not in the Allowed Values list.", i.ReferenceName, value))
        End If
    Next
End Sub

Private Function GetPropertyValue(ByVal path As String, ByVal target As Object) As String
    Dim bits() As String = path.Split(".")
    Dim ll As New LinkedList(Of String)
    Array.ForEach(bits, Function(b) ll.AddLast(b))
    Return GetPropertyRecurse(ll.First, target)
End Function

Private Function GetPropertyRecurse(ByVal node As LinkedListNode(Of String), ByVal target As Object) As String
    ' ToDo: add ability to support propertyName(0) [arrays]
    Dim r As System.Reflection.PropertyInfo = target.GetType.GetProperty(node.Value, BindingFlags.Static Or BindingFlags.Public Or BindingFlags.GetField Or BindingFlags.GetProperty)
    If r.PropertyType.IsClass And Not node.Next Is Nothing Then
        Return GetPropertyRecurse(node.Next, r.GetValue(target, Nothing))
    Else
        Return r.GetValue(target, Nothing).ToString
    End If
End Function&lt;/pre&gt;

&lt;p&gt;Like I said this is work in progress and it does not support arrays as sub values, but it does add a certain level of versatility to the logging. My last project used a logging system, not &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt;, to log errors to TFS in this way and I also added functionality to update the work item in different ways if it was Closed or Resolved to reactivate it depending on the Build number values.&lt;/p&gt;

&lt;p&gt;We have now created a new work item, but what about loading an existing one?&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Private Function GetExistingWorkItem(ByVal Title As String) As WorkItem
    ' Query for work items
    Dim query As String = "SELECT [System.Id], [System.Title] " _
                         &amp;amp; "FROM WorkItems " _
                         &amp;amp; "WHERE [System.TeamProject] = @Project  " _
                         &amp;amp; "AND  [System.WorkItemType] = @WorkItemType  " _
                         &amp;amp; "AND  [System.Title] = @Title  " _
                         &amp;amp; "ORDER BY [System.Id]"
    Dim paramiters As New Hashtable
    paramiters.Add("Project", m_TemplateDefault.TeamProjectName)
    paramiters.Add("WorkItemType", m_TemplateDefault.WorkItemTypeName)
    paramiters.Add("Title", m_TemplateDefault.WorkItemTypeName)
    Dim y As WorkItemCollection = TfsWorkItemStore.Query(query, paramiters)
    Return y(0)
End Function&lt;/pre&gt;

&lt;p&gt;This is a simple search for the title that we created and pass back the first match, just in case we have duplicates.&lt;/p&gt;

&lt;p&gt;And that's all there is to saving your logs into VSTS, but how do we get them out! This is pretty easy as all of our log entries have now been saved to a TFS work item and if you remember from before we used the “String.Format("{0}|{1}", wi.Id, errorId.ToString)“ for the ID so we can find the work item again.&lt;/p&gt;

&lt;p&gt;The two thing we have left is loading a single error, and loading all of the errors. Getting a single error is a little tricky, which is why we passed back the ID in a format that included the Work Item ID.&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Public Overrides Function GetError(ByVal id As String) As ErrorLogEntry
    Dim idBits() As String = id.Split("|")
    Dim wiId As Integer
    Dim errGuid As String
    If Not idBits.Length = 2 Then
        Throw New ArgumentException("Invalid ID, it must be made in the format {workItemId}|{guid}", "id")
    End If
    If Not IsNumeric(idBits(0)) Then
        Throw New ArgumentException("The workItemId part of the ID must be an integer. Format: {workItemId}|{guid}", "id")
    End If
    wiId = CInt(idBits(0))
    Try
        errGuid = New Guid(idBits(1)).ToString
    Catch ex As Exception
        Throw New ArgumentException("The guid part of the ID must be an integer. Format: {workItemId}|{guid}", "id")
    End Try
    Dim wi As WorkItem = TfsWorkItemStore.GetWorkItem(wiId)
    If wi Is Nothing Then
        Throw New ApplicationException("A work item with that id does not exits")
    End If
    Dim a = (From attachemnt As Attachment In wi.Attachments Where attachemnt.Name.Contains(errGuid) Select attachemnt).SingleOrDefault
    If a Is Nothing Then
        Throw New ApplicationException("The attachment does not exits or has been removed")
    End If
    Return GetErrorLogEntryFromTfsAttachement(wi, a)
End Function&lt;/pre&gt;

&lt;p&gt;In this method we do a little validation while parsing out the Work Item ID and the &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt; ID, we then load the specified work item, and find the attachment, and return it. I have a little helper method to make a log item from an attachment, but it fairly simple:&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Private Function GetErrorLogEntryFromTfsAttachement(ByVal wi As WorkItem, ByVal a As Attachment) As ErrorLogEntry
    Using reader = XmlReader.Create(a.Uri.ToString)
        If Not reader.IsStartElement("error") Then
            Return Nothing
        End If
        Dim errid = String.Format("{0}|{1}", wi.Id, reader.GetAttribute("errorId"))
        Dim [error] = ErrorXml.Decode(reader)
        Return New ErrorLogEntry(Me, errid, [error])
    End Using
    Return Nothing
End Function&lt;/pre&gt;

&lt;p&gt;And voila! You havve a single Error Log Entry. As you have probably guesses, getting all the errors is easy now. We just need to find all attachements that have a .&lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;elmah&lt;/a&gt; extension in our project. A little linq can help with this.&lt;/p&gt;

&lt;pre class="brush: vb; highlight: [16];"&gt;Public Overrides Function GetErrors(ByVal pageIndex As Integer, ByVal pageSize As Integer, ByVal errorEntryList As System.Collections.IList) As Integer
    If pageIndex &amp;lt; 0 Then Throw New ArgumentOutOfRangeException("pageIndex", pageIndex, Nothing)
    If pageSize &amp;lt; 0 Then Throw New ArgumentOutOfRangeException("pageSize", pageSize, Nothing)

    ' Query for work items
    Dim query As String = "SELECT [System.Id], [System.Title] " _
                         &amp;amp; "FROM WorkItems " _
                         &amp;amp; "WHERE [System.TeamProject] = @Project  " _
                         &amp;amp; "AND  [System.WorkItemType] = @WorkItemType  " _
                         &amp;amp; "ORDER BY [System.Id]"
    Dim paramiters As New Hashtable
    paramiters.Add("Project", m_TemplateDefault.TeamProjectName)
    paramiters.Add("WorkItemType", m_TemplateDefault.WorkItemTypeName)
    Dim y As WorkItemCollection = TfsWorkItemStore.Query(query, paramiters)
    ' Query work items for attachments
    Dim wiats = From wi As WorkItem In y, a As Attachment In wi.Attachments Where a.Name.Contains(".elmah") Order By a.Name Select a, wi
    If Not wiats Is Nothing Then
        ' Select specific attachemnts
        Dim results = From wiat In wiats Skip pageIndex * pageSize Take pageSize Select wiat
        ' Add to output
        For Each el In results
            errorEntryList.Add(GetErrorLogEntryFromTfsAttachement(el.wi, el.a))
        Next
    End If
    ' return count
    Return errorEntryList.Count
End Function&lt;/pre&gt;

&lt;p&gt;And there we go, errors from &lt;a href="http://code.google.com/p/elmah/" target="_blank"&gt;Elmah&lt;/a&gt; saved into Team Foundation Server and then loaded back out. I don’t know how useful this would be in the real world, but it was good for a little boredom relief.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Full Source&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre class="brush: vb; collapse: true;"&gt;Imports Elmah
Imports Microsoft.TeamFoundation.Client
Imports Microsoft.TeamFoundation.WorkItemTracking.Client
Imports Microsoft.TeamFoundation.PowerTools.Client.WorkItemTracking.Templates
Imports System.Globalization
Imports System.Xml
Imports System.Text
Imports System.Web
Imports System.Reflection

Public Class TfsErrorLog
    Inherits ErrorLog

    Private Shared m_TemplateDefault As Template
    Private Shared m_TemplateErrorMap As Template
    Private Shared sm_Tfs As TeamFoundationServer
    Private Shared sm_TfsStore As WorkItemStore
    Private Shared sm_TfsProject As Project
    Private Shared sm_Config As IDictionary

    Public ReadOnly Property TfsServer() As TeamFoundationServer
        Get
            If sm_Tfs Is Nothing Then
                sm_Tfs = GetTeamFoundationServer()
            End If
            Return sm_Tfs
        End Get
    End Property

    Public ReadOnly Property TfsWorkItemStore() As WorkItemStore
        Get
            If sm_TfsStore Is Nothing Then
                sm_TfsStore = GetTeamFoundationServerWorkItemStore()
            End If
            Return sm_TfsStore
        End Get
    End Property

    Public ReadOnly Property TfsProject() As Project
        Get
            If sm_TfsProject Is Nothing Then
                sm_TfsProject = GetTeamFoundationServerProject()
            End If
            Return sm_TfsProject
        End Get
    End Property

    Public Sub New(ByVal config As IDictionary)
        If config Is Nothing Then
            Throw New ArgumentNullException("config")
        End If
        sm_Config = config

        Dim store As ITemplateStore = GetStore()
        m_TemplateDefault = GetTemplate("Defaults", store)
        m_TemplateErrorMap = GetTemplate("ErrorMap", store)

        If m_TemplateDefault Is Nothing Or m_TemplateErrorMap Is Nothing Then
            Throw New ApplicationException("Unable to load the templates from the store.")
        End If

    End Sub

    Private Function GetStore()
        Dim TfsWorkItemTemplateStore As String = GetStorePath()
        Try
            Dim storeProvider As New FileSystemTemplateStoreProvider
            Return New TemplateStore(storeProvider, TfsWorkItemTemplateStore, ":)Store")
        Catch ex As Exception
            Throw New ApplicationException(String.Format("Unable to load the store from '{0}'.", TfsWorkItemTemplateStore), ex)
        End Try
    End Function

    Private Function GetStorePath() As String
        Dim storePath As String = sm_Config("TfsWorkItemTemplateStore")
        If String.IsNullOrEmpty(storePath) Then
            Throw New ApplicationException("Tfs Server Name is missing for the TFS based error log.")
        End If
        Try
            If storePath.StartsWith("~/") Then
                storePath = HttpContext.Current.Server.MapPath(storePath)
            End If
            Return storePath
        Catch ex As Exception
            Throw New ApplicationException(String.Format("Unable to produce the store path from '{0}'.", storePath), ex)
        End Try
    End Function

    Private Function GetTemplate(ByVal TemplateName As String, ByVal store As ITemplateStore) As ITemplate
        Try
            Dim t As ITemplate
            If Not store.TemplateExists("/", TemplateName) Then
                t = store.CreateTemplate()
                t.Name = TemplateName
                t.ParentFolder = "/"
                t.TeamServerUri = "https://tfs01.codeplex.biz:443"
                t.TeamProjectName = "RDdotNet"
                t.WorkItemTypeName = "WorkItem"
                store.AddTemplate(t)
            End If
            Return store.GetTemplate("/", TemplateName)
        Catch ex As Exception
            Throw New ApplicationException(String.Format("Unable to load the template '{0}' from the store.", TemplateName), ex)
        End Try
    End Function

    Private Function GetTeamFoundationServer() As TeamFoundationServer
        Dim tfs As TeamFoundationServer = Nothing
        Try
            tfs = New TeamFoundationServer(m_TemplateDefault.TeamServerUri)
            tfs.Authenticate()
            If Not tfs.HasAuthenticated Then
                Throw New ApplicationException("Unable to authenticate against TFS server")
            End If
        Catch ex As Exception
            Throw New ApplicationException("Failed to authenticate against TFS server", ex)
        End Try
        Return tfs
    End Function

    Private Function GetTeamFoundationServerWorkItemStore() As WorkItemStore
        Dim store As WorkItemStore = Nothing
        If TfsServer.HasAuthenticated Then
            store = DirectCast(TfsServer.GetService(GetType(WorkItemStore)), WorkItemStore)
        End If
        Return store
    End Function

    Private Function GetTeamFoundationServerProject() As Project
        Dim Project As Project = Nothing
        Try
            If TfsServer.HasAuthenticated Then
                Project = TfsWorkItemStore.Projects(m_TemplateDefault.TeamProjectName)
            End If
        Catch ex As Exception
            Throw New ApplicationException("Unable to retrieve Tfs Project", ex)
        End Try
        If Project Is Nothing Then
            Throw New ApplicationException(String.Format("Unable to locate project with the name '{0}'", m_TemplateDefault.TeamProjectName))
        End If
        Return Project
    End Function

    Public Overrides Function GetError(ByVal id As String) As ErrorLogEntry
        Dim idBits() As String = id.Split("|")
        Dim wiId As Integer
        Dim errGuid As String
        If Not idBits.Length = 2 Then
            Throw New ArgumentException("Invalid ID, it must be made in the format {workItemId}|{guid}", "id")
        End If
        If Not IsNumeric(idBits(0)) Then
            Throw New ArgumentException("The workItemId part of the ID must be an integer. Format: {workItemId}|{guid}", "id")
        End If
        wiId = CInt(idBits(0))
        Try
            errGuid = New Guid(idBits(1)).ToString
        Catch ex As Exception
            Throw New ArgumentException("The guid part of the ID must be an integer. Format: {workItemId}|{guid}", "id")
        End Try
        Dim wi As WorkItem = TfsWorkItemStore.GetWorkItem(wiId)
        If wi Is Nothing Then
            Throw New ApplicationException("A work item with that id does not exits")
        End If
        Dim a = (From attachemnt As Attachment In wi.Attachments Where attachemnt.Name.Contains(errGuid) Select attachemnt).SingleOrDefault
        If a Is Nothing Then
            Throw New ApplicationException("The attachment does not exits or has been removed")
        End If
        Return GetErrorLogEntryFromTfsAttachement(wi, a)
    End Function

    Public Overrides Function GetErrors(ByVal pageIndex As Integer, ByVal pageSize As Integer, ByVal errorEntryList As System.Collections.IList) As Integer
        If pageIndex &amp;lt; 0 Then Throw New ArgumentOutOfRangeException("pageIndex", pageIndex, Nothing)
        If pageSize &amp;lt; 0 Then Throw New ArgumentOutOfRangeException("pageSize", pageSize, Nothing)

        ' Query for work items
        Dim query As String = "SELECT [System.Id], [System.Title] " _
                             &amp;amp; "FROM WorkItems " _
                             &amp;amp; "WHERE [System.TeamProject] = @Project  " _
                             &amp;amp; "AND  [System.WorkItemType] = @WorkItemType  " _
                             &amp;amp; "ORDER BY [System.Id]"
        Dim paramiters As New Hashtable
        paramiters.Add("Project", m_TemplateDefault.TeamProjectName)
        paramiters.Add("WorkItemType", m_TemplateDefault.WorkItemTypeName)
        Dim y As WorkItemCollection = TfsWorkItemStore.Query(query, paramiters)
        ' Query work items for attachments
        Dim wiats = From wi As WorkItem In y, a As Attachment In wi.Attachments Where a.Name.Contains(".elmah") Order By a.Name Select a, wi
        If Not wiats Is Nothing Then
            ' Select specific attachemnts
            Dim results = From wiat In wiats Skip pageIndex * pageSize Take pageSize Select wiat
            ' Add to output
            For Each el In results
                errorEntryList.Add(GetErrorLogEntryFromTfsAttachement(el.wi, el.a))
            Next
        End If
        ' return count
        Return errorEntryList.Count
    End Function

    ''' &amp;lt;summary&amp;gt;
    ''' Logs the error as an attachement to an existing work item, or adds a new work item if this error has not occured.
    ''' &amp;lt;/summary&amp;gt;
    ''' &amp;lt;param name="error"&amp;gt;The error to be logged&amp;lt;/param&amp;gt;
    ''' &amp;lt;returns&amp;gt;The ID of the error&amp;lt;/returns&amp;gt;
    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;
    Public Overrides Function Log(ByVal [error] As [Error]) As String
        'TODO: Log
        Dim errorId = Guid.NewGuid().ToString()
        Dim timeStamp = DateTime.UtcNow.ToString("yyyy-MM-ddHHmmssZ", CultureInfo.InvariantCulture)
        Dim Filename = String.Format("error-{0}-{1}.elmah", timeStamp, errorId)
        Dim temp = System.IO.Path.Combine(".", Filename)
        ' Temp Log to disk
        Using writer = New XmlTextWriter(temp, Encoding.UTF8)
            writer.Formatting = Formatting.Indented
            writer.WriteStartElement("error")
            writer.WriteAttributeString("errorId", errorId)
            ErrorXml.Encode([error], writer)
            writer.WriteEndElement()
            writer.Flush()
        End Using

        Dim Title As String = String.Format("{0}-{1}", [error].ApplicationName, [error].Message)

        Dim wi As WorkItem = GetWorkItemForException(Title, [error])

        Dim a As New Attachment(temp, "Elmah error log")

        wi.Attachments.Add(a)
        If wi.IsValid Then
            wi.Save()
            Return String.Format("{0}|{1}", wi.Id, errorId.ToString)
        Else
            Dim message As New System.Text.StringBuilder
            Dim results = wi.Validate()
            Dim isFirst As Boolean = True
            For Each r In results
                message.AppendLine(String.Format(IIf(isFirst, "{0}", ", {0}"), r))
                isFirst = False
            Next
            Throw New ApplicationException(String.Format("Unable to save the work item becuse the following fields produced a validation error '{0}'.", message.ToString))
        End If
    End Function

    Protected Function GetWorkItemForException(ByVal Title As String, ByVal [error] As [Error]) As WorkItem
        Dim wi As WorkItem = GetExistingWorkItem(Title)
        If wi Is Nothing Then
            wi = CreateNewWorkItem(Title)
        End If
        m_TemplateDefault.Fields.ApplyFieldValues(wi, False)
        ApplyErrorFieldValues(wi, [error])
        Return wi
    End Function

    Private Function GetExistingWorkItem(ByVal Title As String) As WorkItem
        ' Query for work items
        Dim query As String = "SELECT [System.Id], [System.Title] " _
                             &amp;amp; "FROM WorkItems " _
                             &amp;amp; "WHERE [System.TeamProject] = @Project  " _
                             &amp;amp; "AND  [System.WorkItemType] = @WorkItemType  " _
                             &amp;amp; "AND  [System.Title] = @Title  " _
                             &amp;amp; "ORDER BY [System.Id]"
        Dim paramiters As New Hashtable
        paramiters.Add("Project", m_TemplateDefault.TeamProjectName)
        paramiters.Add("WorkItemType", m_TemplateDefault.WorkItemTypeName)
        paramiters.Add("Title", m_TemplateDefault.WorkItemTypeName)
        Dim y As WorkItemCollection = TfsWorkItemStore.Query(query, paramiters)
        Return y(0)
    End Function

    Private Function CreateNewWorkItem(ByVal Title As String) As WorkItem
        Dim wit As WorkItemType = (From t As WorkItemType In TfsProject.WorkItemTypes Where t.Name = m_TemplateDefault.WorkItemTypeName).SingleOrDefault
        If wit Is Nothing Then
            Throw New ApplicationException(String.Format("Unable to find the work item type '{0}' in the project '{1}'", m_TemplateDefault.WorkItemTypeName, TfsProject.Name))
        End If
        Dim wi As New WorkItem(wit)
        wi.Title = Title
        Return wi
    End Function

    Private Sub ApplyErrorFieldValues(ByVal wi As WorkItem, ByVal [error] As [Error])
        For Each i In m_TemplateErrorMap.Fields
            Dim value As String = GetPropertyValue(i.Value, [error])
            If wi.Fields(i.ReferenceName).AllowedValues.Contains(value) Then
                wi.Fields(i.ReferenceName).Value = value
            Else
                Throw New ApplicationException(String.Format("Unable to set the work item field '{0}' to '{1}' as '{1}' is not in the Allowed Values list.", i.ReferenceName, value))
            End If
        Next
    End Sub

    Private Function GetPropertyValue(ByVal path As String, ByVal target As Object) As String
        Dim bits() As String = path.Split(".")
        Dim ll As New LinkedList(Of String)
        Array.ForEach(bits, Function(b) ll.AddLast(b))
        Return GetPropertyRecurse(ll.First, target)
    End Function

    Private Function GetPropertyRecurse(ByVal node As LinkedListNode(Of String), ByVal target As Object) As String
        ' ToDo: addd ability to support propertyName(0) [arrays]
        Dim r As System.Reflection.PropertyInfo = target.GetType.GetProperty(node.Value, BindingFlags.Static Or BindingFlags.Public Or BindingFlags.GetField Or BindingFlags.GetProperty)
        If r.PropertyType.IsClass And Not node.Next Is Nothing Then
            Return GetPropertyRecurse(node.Next, r.GetValue(target, Nothing))
        Else
            Return r.GetValue(target, Nothing).ToString
        End If
    End Function

    Private Function GetErrorLogEntryFromTfsAttachement(ByVal wi As WorkItem, ByVal a As Attachment) As ErrorLogEntry
        Using reader = XmlReader.Create(a.Uri.ToString)
            If Not reader.IsStartElement("error") Then
                Return Nothing
            End If
            Dim errid = String.Format("{0}|{1}", wi.Id, reader.GetAttribute("errorId"))
            Dim [error] = ErrorXml.Decode(reader)
            Return New ErrorLogEntry(Me, errid, [error])
        End Using
        Return Nothing
    End Function

End Class&lt;/pre&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4afa5abb-f3bb-4078-9e38-bc3b1d1b68e8" class="wlWriterSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Elmah" rel="tag"&gt;Elmah&lt;/a&gt;,&lt;a href="http://technorati.com/tags/VSTS+Planning+%26+Tracking" rel="tag"&gt;VSTS Planning &amp;amp; Tracking&lt;/a&gt;,&lt;a href="http://technorati.com/tags/VSTS" rel="tag"&gt;VSTS&lt;/a&gt;,&lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/VB.NET" rel="tag"&gt;VB.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/VB" rel="tag"&gt;VB&lt;/a&gt;,&lt;a href="http://technorati.com/tags/TFS" rel="tag"&gt;TFS&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133726"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133726" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/133726.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood (DyslexicDev)</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/07/26/log-elmah-errors-in-team-foundation-server.aspx</guid>
            <pubDate>Sun, 26 Jul 2009 21:30:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/133726.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/07/26/log-elmah-errors-in-team-foundation-server.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/133726.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/133726.aspx</trackback:ping>
        </item>
        <item>
            <title>Disable a timer at every level of your ASP.NET control hierarchy</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/07/22/disable-a-timer-at-every-level-of-your-asp.net-control.aspx</link>
            <description>&lt;p&gt;Even though this sounds like a really simple thing, what if you do not know the name of the controls, and you do not want to have to add a bit of code that you, or another may developer may forget to every piece of code with a timer in it. The problem I have is that if you have a DropDownList on the same page as a update panel that updates based on a timer, you get a little interference.&lt;/p&gt;  &lt;p&gt;If the user has the DropDownList open when the update occurs then the DropDownList closes. Very annoying.&lt;/p&gt;  &lt;p&gt;The standard FindControl does not work as it requires an ID, so what if all you have is a type?&lt;/p&gt;  &lt;p&gt;Well, you need a little extension method :)&lt;/p&gt;  &lt;pre class="brush: vb;"&gt;Imports System.Runtime.CompilerServices
Imports System.Web
Imports System.Web.UI

Module WebExtensions

    &amp;lt;Extension()&amp;gt; _
    Friend Sub FindControls(Of T)(ByVal control As Control, ByVal list As List(Of T))
        If control.HasControls Then
            Dim timers = control.Controls.OfType(Of T)()
            list.AddRange(timers)
            Dim subcontrols = From c In control.Controls Where Not timers.Cast(Of Control).Contains(c)
            For Each c In subcontrols.Cast(Of Control)()
                c.FindControls(Of T)(list)
            Next
        End If
    End Sub

    &amp;lt;Extension()&amp;gt; _
    Friend Function FindControls(Of T)(ByVal control As Control) As List(Of T)
        Dim l As New List(Of T)
        control.FindControls(Of T)(l)
        Return l
    End Function

End Module&lt;/pre&gt;

&lt;p&gt;I am pretty sure this is not the most efficient of code, and any recommendation on improving it are welcome…&lt;/p&gt;

&lt;p&gt;Once this is in place it is easily called and actioned upon:&lt;/p&gt;

&lt;pre class="brush: vb;"&gt;Sub OnPagePreRender(ByVal sender As Object, ByVal e As EventArgs)

    ' Fix for pages with drop down lists
    FixForDropdownListsAndTimers()
End Sub

Private Sub FixForDropdownListsAndTimers()
    ' Provcess timers
    Me.FindControls(Of System.Web.UI.Timer).ForEach(New Action(Of System.Web.UI.Timer)(AddressOf ProcessTimers))
End Sub

Private Sub ProcessTimers(ByVal t As System.Web.UI.Timer)
    t.Enabled = Not DisableTimers
End Sub&lt;/pre&gt;

&lt;p&gt;DisableTimers is set at the page level and filters down to the control so we can now disable all timers on a page when we want.&lt;/p&gt;

&lt;p&gt;The FindControls method can find a list of all instances of a control type from an entire page, regardless of the nesting…&lt;/p&gt;

&lt;p&gt;&lt;font color="#ff0000"&gt;UPDATE: OK, so you have probably guessed that I am a complete &lt;strong&gt;&lt;em&gt;muppet&lt;/em&gt;&lt;/strong&gt;.. I have changes my UpdatePanels to UpdateMode=“Conditional” and with a few extra lines of code solved my problem the correct way! I will be keeping this little bit of code as you never know when you need to find all instances of a type of control :)… I am such a donkey…&lt;/font&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:91037586-1a3e-4f25-ad05-2e25cdbb1f3f" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/ASP.NET" rel="tag"&gt;ASP.NET&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Extension" rel="tag"&gt;Extension&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Extension+Methods" rel="tag"&gt;Extension Methods&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASP" rel="tag"&gt;ASP&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASP.NET+Ajax" rel="tag"&gt;ASP.NET Ajax&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133665"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=133665" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/133665.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/07/22/disable-a-timer-at-every-level-of-your-asp.net-control.aspx</guid>
            <pubDate>Wed, 22 Jul 2009 21:26:25 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/133665.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/07/22/disable-a-timer-at-every-level-of-your-asp.net-control.aspx#feedback</comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/133665.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/133665.aspx</trackback:ping>
        </item>
        <item>
            <title>Uninstalling Visual Studio 2010 Beta 1</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/05/19/uninstalling-visual-studio-2010-beta-1.aspx</link>
            <description>&lt;p&gt;You may think, why is he uninstalling VS2010? Well, apart from proving that it works…And that it plays well with VS2008 I need to remove the pre-beta beta that I have installed.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_2.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_thumb.png" width="504" height="385" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This is in fact the second time I have uninstalled VS2010 on this computer, and I had no problems last time, but the difference is that I will be installing a slightly different build :) of Beta 1.&lt;/p&gt;  &lt;p&gt;I am hoping that I do not have any problems, but my scenario is largely unsupported.&lt;/p&gt;  &lt;p&gt;I have removed visual studio, but it probably left a few trainer that I will need to remove manually. The easiest way is to see what was installed in the last month and check it all… Gruelling I know, but what can you do…&lt;/p&gt;  &lt;p&gt;There is a nice little feature in Vista when you are in the programs list that lets you filter the list… coz it can be realy big&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_thumb_1.png" width="504" height="254" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here is he list of software I have installed in the last month:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_6.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_thumb_2.png" width="504" height="604" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;I have highlighted all of the 2010 bits and it at first seams like there are rather a lot of them, but as you go through the list (I will finish with the .NET 4.0 bits) you find that it is just a cleanup issue..&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_thumb_3.png" width="504" height="150" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;So I then had some fun uninstalling .NET 4.0…&lt;/p&gt;  &lt;p&gt;I know that this was unsupported, and that we were warned us not to do it, but we are developers and we like to push the big red buttons, but I installed the pre-beta beta on my production computer…&lt;/p&gt;  &lt;p&gt;During the uninstall there was an infinite number of runtime errors.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/clip_image002_2.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/clip_image002_thumb.jpg" width="244" height="138" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And after cancelling and rebooting received lots of .net 4.0 errors for all sorts of applications upon boot.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/clip_image004_2.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/clip_image004_thumb.jpg" width="244" height="86" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The same thing happened during my second attempt at uninstalling. The plan now is to try a repair and then an uninstall...&lt;/p&gt;  &lt;p&gt;Well, the repair failed, so I am going strait to installing from the new .NET 4.0 Beta 1 release and everything seams to be working ok so far. I realise that my computer will be in an unknown state afterwards, but I can always reinstall when I get the chance.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/UninstallingVisualStudio2010Beta1_7977/image_thumb_4.png" width="244" height="228" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt; And after a restart, no problems… Wohooo….&lt;/p&gt;  &lt;p&gt;Now to VS2010… And if my infrastructure team get me my VPC there will be &lt;a title="Team Foundation Server" href="http://msdn2.microsoft.com/en-us/teamsystem/aa718934.aspx" target="_blank"&gt;TFS&lt;/a&gt; fun as Well.&lt;/p&gt;  &lt;p&gt;So the end result is that although I have not uninstalled .NET 4.0, I do have the latest version which is what I wanted…&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e286052e-97dd-4054-aaf8-c783a90a94ce" class="wlWriterEditableSmartContent"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Uninstall" rel="tag"&gt;Uninstall&lt;/a&gt;,&lt;a href="http://technorati.com/tags/.NET+Framework+4.0+Beta+1" rel="tag"&gt;.NET Framework 4.0 Beta 1&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Visual+Studio+2010+Beta+1" rel="tag"&gt;Visual Studio 2010 Beta 1&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132257"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132257" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/132257.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/05/19/uninstalling-visual-studio-2010-beta-1.aspx</guid>
            <pubDate>Tue, 19 May 2009 10:10:18 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/132257.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/05/19/uninstalling-visual-studio-2010-beta-1.aspx#feedback</comments>
            <slash:comments>8</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/132257.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/132257.aspx</trackback:ping>
        </item>
        <item>
            <title>Visual Studio 2010 Supports UML</title>
            <link>http://geekswithblogs.net/hinshelm/archive/2009/05/18/visual-studio-2010-supports-uml.aspx</link>
            <description>&lt;p&gt;&lt;img title="VS-TS_rgb_thumb[2][5][5][5][5]" border="0" alt="VS-TS_rgb_thumb[2][5][5][5][5]" align="right" width="240" height="136" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/VisualStudio2010SupportsUML_EC8C/VS-TS_rgb_thumb%5B2%5D%5B5%5D%5B5%5D%5B5%5D%5B5%5D_def9b12e-d358-4645-9513-3af8b88e5b67.png" /&gt;Just in case you have been living in a shed at the bottom of the garden, Visual Studio 2010 is to support UML. As you can see from my diagram, my UML skills are a little, erm, crude. But I think you will get the picture and if you want to do better then just download &lt;a target="_blank" href="http://www.microsoft.com/visualstudio/en-gb/products/2010/default.mspx"&gt;Visual Studio 2010 on Wednesday&lt;/a&gt; if you are not an MSDN subscribe, and if you are… well you can get it today :)&lt;/p&gt;
&lt;p&gt;&lt;img title="image_thumb[4]" border="0" alt="image_thumb[4]" width="504" height="323" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" src="http://geekswithblogs.net/images/geekswithblogs_net/hinshelm/WindowsLiveWriter/VisualStudio2010SupportsUML_EC8C/image_thumb%5B4%5D_c81fe793-cef5-4cdf-9fbc-02bfd8d8f4ba.png" /&gt;&lt;/p&gt;
&lt;p&gt;As I have not used UML since university so I do not know if this feature will meet the needs of those that use UML extensively, but I would expect that a lot of time and investment has gone into this area, and if it is lacking in some minor but crucial feature, there is still time to get some changes made…maybe...&lt;/p&gt;
&lt;div id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e0640bb7-fc8d-41ca-8bdb-2102c7081c91" class="wlWriterSmartContent" style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px"&gt;Technorati Tags: &lt;a rel="tag" href="http://technorati.com/tags/UML"&gt;UML&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/Visual+Studio+2010"&gt;Visual Studio 2010&lt;/a&gt;,&lt;a rel="tag" href="http://technorati.com/tags/Visual+Studio+2010+Beta+1"&gt;Visual Studio 2010 Beta 1&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132212"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=132212" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/hinshelm/aggbug/132212.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Martin Hinshelwood (SSW)</dc:creator>
            <guid>http://geekswithblogs.net/hinshelm/archive/2009/05/18/visual-studio-2010-supports-uml.aspx</guid>
            <pubDate>Mon, 18 May 2009 15:49:26 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/hinshelm/comments/132212.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/hinshelm/archive/2009/05/18/visual-studio-2010-supports-uml.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/hinshelm/comments/commentRss/132212.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/hinshelm/services/trackbacks/132212.aspx</trackback:ping>
        </item>
    </channel>
</rss>