.Net Best Practices Event

Wednesday, April 01, 2009 3:32:59 AM (GMT Daylight Time, UTC+01:00)

Here is the deck and code samples I presented for the .NET Best Practices event that was hosted in St. Louis, Missouri on March 24th and in Bloomington, Mn on March 31st.

Building Loosely Coupled Applications

DeckAndCode.zip (2.58 MB)

MSDN Presentation: Lap Around the Live Framework and Mesh Services

Friday, January 16, 2009 6:30:31 PM (GMT Standard Time, UTC+00:00)

Here is the presentation and code samples I delivered last Tuesday at the MSDN Developer Conference.  Let me know if you have any problems getting the demos running or have questions.

MSDN Developer Conference Coming Tuesday Jan. 13th, 2009…

Saturday, January 10, 2009 5:18:10 PM (GMT Standard Time, UTC+00:00)

I am speaking on Microsoft’s Live Framework  and Live Mesh.  It also looks like they are going to have some great door prizes.  Check it out.

image

Pasting Slides in PowerPoint, Messes Up My Custom Diagrams

Tuesday, December 16, 2008 4:06:03 AM (GMT Standard Time, UTC+00:00)

Typically when I speak at events I get a deck that has a custom layout and color palette.  If I am creating my own material I typically paste existing slides with diagrams I have constructed from past presentations or guidance which had completely different layouts and themes.  This results in diagrams that typically have color issues or limited color palette to select from.  Here is an example of one very simple diagram that had some animation to explain how you could take advantage of animation to create a better user experience.

image

Notice how the the options for Quick Styles has no variation in color and my drawing inherited very basic colors with the variations shown in the drop down.  You can introduce more colors by selecting from a number of available themes buried in the Slide Master.  To access these themes do the following:

Click on the View Tab, then select Slide Master.

image

Next, select the Colors dropdown.

image

From there you will get a list of Presentation theme palettes and Built-In palettes.  Since I draw all of my diagrams/graphics using the Office theme, I can now select that and utilize the color variation in the Office theme to create consistent looking diagrams across different presentation templates and when these diagrams are pasted into the new presentations, they look the same.

image

Below is the diagram from above with the built-in office theme and the use of Quick Styles.

image

Insulating against grid row order changes in WPF

Tuesday, December 16, 2008 1:40:21 AM (GMT Standard Time, UTC+00:00)

One of the things that I don't like about the WPF Grid is the fact that if you insert new rows into a grid layout control you have to update the Grid.Row attached property to ensure that the rows render in proper order.

For example, if you supplied xaml that showed contact information and looked something like this:

image

here is the xaml representation:

<Border BorderBrush="LightGray" BorderThickness="1" Padding="10" CornerRadius="10">
            <Grid>
                <Grid.Resources>
                    <Thickness x:Key="Rowspacing">7</Thickness>
                </Grid.Resources>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"  />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
 
                <Label  Grid.Row="0" Content="First Name:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right" />
                <Label  Grid.Row="1" Content="Last Name:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="2" Content="Street Address:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="3" Content="City:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="4" Content="State:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="5" Content="Zip:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="6" Content="Company:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
 
 
                <TextBox  Grid.Column="1" Grid.Row="0" Text="Shannon" MinWidth="300" VerticalAlignment="Center" />
                <TextBox  Grid.Column="1" Grid.Row="1" Text="Braun" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="2" Text="111 Main Street" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="3" Text="Minneapolis" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="4" Text="Mn" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="5" Text="55414" AcceptsReturn="True"  VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="6" Text="Sysknowlogy" AcceptsReturn="True"  VerticalAlignment="Center"></TextBox>
                
            </Grid>
        </Border>

If I wanted to insert a row between Grid.Row="0" (First Name) and Grid.Row="1" (Last Name) I would have to also update the Grid.Row attached property for all of the rows after the insert. 

One of the ways to get around this is to bind the Grid.Row attached property on the Labels and Textboxes to the Index of the RowDefinition. When a RowDefinition is inserted or moved there is no need to update the indexes.  Unfortunately the RowDefinition doesn't expose a Index, so using the Binding facilities of WPF won't work here.  Instead we will leverage a MarkupExtension to translate the the reference to the RowDefinition name to the actual index of that RowDefinition, insulating us from any row inserts or changes in order.

The first step is to add a name to each of the RowDefinitions so that we can reference them.

<RowDefinition x:Name="Row_FirstName" Height="Auto"  />
<RowDefinition x:Name="Row_LastName" Height="Auto" />
<RowDefinition x:Name="Row_Street" Height="Auto" />
<RowDefinition x:Name="Row_City" Height="Auto" />
<RowDefinition x:Name="Row_State" Height="Auto" />
<RowDefinition x:Name="Row_Zip" Height="Auto" />
<RowDefinition x:Name="Row_Company" Height="Auto" />

Write the MarkUpExtension that will support the translation from element name to row index... the result looks like the following:

[MarkupExtensionReturnType(typeof(int))]
public class MapTo : MarkupExtension
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MapTo"/> class.
    /// </summary>
    public MapTo()
    {
    }
 
    /// <summary>
    /// Initializes a new instance of the <see cref="MapTo"/> class.
    /// </summary>
    /// <param name="rowName">Name of the row.</param>
    public MapTo(string rowName)
    {
        _name = rowName;
    }
 
    private string _name;
    /// <summary>
    /// Gets or sets the name of the element.
    /// </summary>
    /// <value>The name of the element.</value>
    public string ElementName
    {
        get { return _name; }
        set { _name = value; }
    }
 
    /// <summary>
    /// When implemented in a derived class, returns an object that is set as the value of the target property for this markup extension.
    /// </summary>
    /// <param name="serviceProvider">Object that can provide services for the markup extension.</param>
    /// <returns>
    /// The object value to set on the property where the extension is applied.
    /// </returns>
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
 
        IProvideValueTarget ipvt = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
 
        int idx = -1;
        if (ipvt != null)
        {
            
            FrameworkElement target = ipvt.TargetObject as FrameworkElement;
            if (target != null)
            {
                
                Grid grd = target.Parent as Grid;
                if (grd != null)
                {
                    idx = GetRowIndex(grd);
                }
                else
                    throw new NullReferenceException("Grid was not found as the parent of element " + _name);
            }
        }
 
        return idx;
 
    }
 
    /// <summary>
    /// Gets the index of the row based on the name of the element.
    /// </summary>
    /// <param name="parent">The parent.</param>
    /// <returns></returns>
    private int GetRowIndex(Grid parent)
    {
        int idx = -1;
        if (parent != null)
        {
            RowDefinition rowDefinition = parent.FindName(_name) as RowDefinition;
 
            if (rowDefinition != null)
            {
                idx = parent.RowDefinitions.IndexOf(rowDefinition);
            }
            else
                throw new NullReferenceException("RowDefinition was not found for name " + _name);
        }
 
        return idx;
    }
}

Next we use the MapTo MarkUpExtension in xaml to identify the row index for both the Labels and TextBoxes:

<Border BorderBrush="LightGray" BorderThickness="1" Padding="10" CornerRadius="10">
            <Grid>
                <Grid.Resources>
                    <Thickness x:Key="Rowspacing">7</Thickness>
                </Grid.Resources>
                <Grid.RowDefinitions>
                    <RowDefinition x:Name="Row_FirstName" Height="Auto"  />
                    <RowDefinition x:Name="Row_LastName" Height="Auto" />
                    <RowDefinition x:Name="Row_Street" Height="Auto" />
                    <RowDefinition x:Name="Row_City" Height="Auto" />
                    <RowDefinition x:Name="Row_State" Height="Auto" />
                    <RowDefinition x:Name="Row_Zip" Height="Auto" />
                    <RowDefinition x:Name="Row_Company" Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
 
                <Label  Grid.Row="{local:MapTo Row_FirstName}" Content="First Name:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right" />
                <Label  Grid.Row="{local:MapTo Row_LastName}" Content="Last Name:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="{local:MapTo Row_Street}" Content="Street Address:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="{local:MapTo Row_City}" Content="City:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="{local:MapTo Row_State}" Content="State:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="{local:MapTo Row_Zip}" Content="Zip:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
                <Label  Grid.Row="{local:MapTo Row_Company}" Content="Company:" Margin="{StaticResource Rowspacing}" HorizontalAlignment="Right"/>
 
 
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_FirstName}" Text="Shannon" MinWidth="300" VerticalAlignment="Center" />
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_LastName}" Text="Braun" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_Street}" Text="111 Main Street" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_City}" Text="Minneapolis" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_State}" Text="Mn" AcceptsReturn="True"   VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_Zip}" Text="55414" AcceptsReturn="True"  VerticalAlignment="Center"></TextBox>
                <TextBox  Grid.Column="1" Grid.Row="{local:MapTo Row_Company}" Text="Sysknowlogy" AcceptsReturn="True"  VerticalAlignment="Center"></TextBox>
 
            </Grid>
        </Border>

To add additional rows, add a new RowDefinition with a name and then map the Grid.Row attached property to the name of the row.

Download Project: GridLayoutApproach.zip

PDC 2008 - Microsoft shows huge commitment to WPF in development tools

Thursday, October 30, 2008 10:08:30 PM (GMT Standard Time, UTC+00:00)

Microsoft has used WPF to write tools in the past... Expression Blend and Design being two of those tools among others.  Its extremely exciting to see that they are making even a bigger commitment to WPF as a platform for writing applications.  This week at PDC they announced that the shell of the Visual Studio 2010 IDE will be written in WPF.  Since Visual Studio has a huge legacy code base and many tools already built a top the DTE, not all of it will be converted to WPF and managed code.  However, one of the most noticeable changes will be that the code editor will be written using the rich text capabilities of WPF... which means that we will now have a very powerful presentation model (rich text, animation, etc) in the IDE that we can leverage to build better IDE experiences. This also means that the bar for extending Visual Studio IDE will be greatly reduced.

Customizing the Visual Studio Start Page

One of the extension points for VS 10 will be modifying the start page... which is possible today, but the model for integrating into other aspects of the IDE (like macros or commands) will be far simpler than what we have today.  To customize the home page  will require you to modify the Xaml file that is found in Documents\Visual Studio 10\Start Page\StartPage.xaml.  To integrate with Visual Studio commands will be a matter of passing in a well-known string identifier for the command.

Managed Extension Framework (MEF) enables the Add-In Model

The new text editor will be composed of MEF components which can be swapped out and customized by supplying your own implementation.  The customization capabilities will be limited to the following areas :

Classification: Rich Text Formatting

- Which will allow us to create a richer reading environment for code.

- Ability to leverage WPF's rich text capabilities.

 

Adornments: Power Graphics

Any WPF visual - can render a UI element anywhere.

- Associate adornments with text, render comments in the MSDN document style inline with code.

- Support for animation and behavior of different aspects of the code.

 

Margin and Scrollbar Customization

- Allows for the ability to create visual representations of structure in the margins of the code editor... this looked very similar to the way ReSharper implemented their Marker Bar (shown below).

image

 

 

Intellisense and Smart Tags

- Contribute to completion of Intellisense ... meaning that we can now filter items.  For a long time I have wanted the ability to modify the intellisense so that when I need to I can just view only the properties, methods or events for a type... and it looks like now the bar may be lowered enough to implement something like this relatively easily.

- Override the presentation of the parameter help or quick info

- Add menu items to smart tags

 

If you want more information, you can check out the videos on channel9

PDC 2008 - Day 2 Keynote

Wednesday, October 29, 2008 12:51:04 AM (GMT Standard Time, UTC+00:00)

Yesterday's keynote talked heavily about infrastructure... today was focused Windows 7 and the frameworks /services we use to build applications in the cloud.  They did a cursory review of the new features of Windows 7 with a focus on behavior and user experience.  They also drilled down into some of the new features that appeal to more of a power user... the ability to create and attach to VHD's from within Windows and even boot to them if you would like.  It also showed more capability around configuring multi-monitors... ability to remote desktop into another machine which will then use your multi-monitor setup (that's cool).  They also said that they are focused on creating a quality OS and they will not release Windows 7 until it is ready. 

Check out the E7 Blog and give feedback on Windows 7.

 

They also made a number of important announcements around WPF and Silverlight:

  • Releasing the Ribbon control for WPF in CTP form
  • Adding touch events onto WPF elements to support multi-touch
  • Released controls include DataGrid, DatePicker, Calendar and Visual State Manager

Visual Studio 2010 will be built on WPF!!!!!

  • It will support richer code editing support
  • It will utilize the Managed Extensibility Framework to extend Visual Studio... which simplifies the add-in model. 

 

Silverlight

  • Added the following controls to Silverlight 2.0... Chart, Treeview, DockPanel, WrapPanel, Viewbox, Expander, Autocomplete and a couple of others.
  • Enabling the ability to run Silverlight both on the desktop and browser

WPF Office Ribbon and other goodies released at PDC

Tuesday, October 28, 2008 10:55:06 PM (GMT Standard Time, UTC+00:00)

You can get the newest WPF Ribbon, DatePicker/Calendar control, preview of VisualStateManager (VSM) for WPF from the WPF Toolkit site... in addition the DataGrid is now out of CTP and was released.

image

PDC 2008 - Blend Tips & Tricks

Tuesday, October 28, 2008 12:48:07 AM (GMT Standard Time, UTC+00:00)

I was a little disappointed in the content of this presentation.  There wasn't as many Tips & Tricks as I would have expected.  One of the tips they attempted to show (which the demo actually failed) involved showing what happens when you try to access an object that isn't available on the Blend design surface... the result on the design surface is an exception that keeps you the user from previewing the UI. If I recall correctly they were were trying to check whether the Page object was available by checking the IsEnabled property, which seems a bit unusual.  I have ran into similar issues with Blend and this is the trick I have used before accessing an object that may not be available when the UI is rendered on the design surface.

/// <summary>
    /// Base class for all Parts in the Shell
    /// </summary>
    public class UIPart : System.Windows.Controls.UserControl, IPart
    {
        
        #region Constructors
 
        /// <summary>
        /// Initializes a new instance of the <see cref="UIPart"/> class.
        /// </summary>
        public UIPart()
        {
            //if we don't check this... the UI will not display correctly in the designer.
            if (InDesignMode)
                return;
 
            partIdField = this.GetType().Name + "_" + Guid.NewGuid();
 
            this.GotFocus += UIPart_GotFocus;
            this.Loaded += UIPart_Loaded;
            this.IsVisibleChanged += UIPart_IsVisibleChanged;
            this.Initialized += UIPart_Initialized;
        }
 
        /// <summary>
        /// Gets a value indicating whether [in design mode].
        /// </summary>
        /// <value><c>true</c> if [in design mode]; otherwise, <c>false</c>.</value>
        public bool InDesignMode
        {
            get { return System.ComponentModel.DesignerProperties.GetIsInDesignMode(this); }
        }

One thing that I did gleam from the talk was that there is a new version of Snoop  available that has the capability to render the composition of an application in a 3D model, the composite model of Blend is shown below:

blendcomposte3d

PDC 2008 Keynote

Tuesday, October 28, 2008 12:23:16 AM (GMT Standard Time, UTC+00:00)

Announced Windows Azure - Web Tier offering that can be thought of as Windows in the cloud. 

  • Scalable Storage
  • Scalable Computing Power
  • Services Lifecycle Management

The systems that are being built today are laying the ground work for the next 50 years. 

Services platform will include the following support:

  • Live Services - Acts as a bridge between devices (phones, laptops and other devices)
  • .NET Services - Workflow, authorization and identity federation.
  • SQL Services - Data Store
  • SharePoint Services - Collaboration
  • Dynamics CRM Services - Business Content

Ray pointed out, that even though they aren't the first to enter the cloud services arena (Amazon just went out of beta this week with their offering EC2), they have some key components that allow them to provider a better platform:

  • Microsoft is consuming their own cloud services to build Microsoft offerings in the cloud. 
  • Microsoft will use the existing tools we have today to build systems that run in the cloud.

 

Demo - Building Cloud Applications... was a basic demo of how you could build a ASP.NET web site and use the Azure console to upload a package (binaries and configuration meta data) to be deployed to the platform for serving up the information.

Demo - Bluehoo.com

Social Networking application that shows you who is around you based on BlueTooth protocol on your cell phone.  Similar to how you detect wireless networks... except you are detecting people that are part of the Bluehoo network.  Bluehoo is utilizing Windows Azure to support their application scalability.

m.bluehoo.com - beta is available later today.