XAML Power Toys 4.0 Released – Code Name MVVM

February 10, 2009

Over the last few months I’ve received many emails requesting features and I’ve got a few of my own that I’ve added to XAML Power Toys!

New Features In v4.0

Added Two New Videos that cover these new features.  Please watch them.

I’ve updated the Control Defaults section of the XAML Power Toys Home Page.  Please read this section as it explains some of the below new features.

  • Extract properties to a Style allows selecting a control, choosing desired properties and have those selected properties extracted to a newly created style
  • Create ViewModel Class from a VB.NET or C# code window.  Easily create a ViewModel stub that includes commands and exposed data class.
  • Group into GroupBox
  • Option to generate x:Name for controls
  • Option to add ForeReRead converter to TextBox bindings (both VB.NET & C# converters included in source and binary downloads.  Converter is also included in the OceanFramework.WPF namespace.)
  • Option to add TargetNullValue to TextBox.Text bindings when Source property is Nullable
  • Corrected secondary application domain load issue reported by DevExpress.  This fix also solves another edge case secondary application domain load issue.

Downloads

See XAML Power Toys Home Page.

Have a great day!

Just a grain of sand on the worlds beaches.


All New XAML Power Toys Videos Published

October 25, 2008

I have remade all the XAML Power Toys videos and published them on the XAML Power Toys Home Page.

The videos are shorter in length and more granular.  The Form, DataGrid & ListView videos all use the Design Time Data Feature to enhance the video with live design time data during the layout process.

New Features In v3.4.0.1

I also corrected the WPF DataGrid comment that is emitted when the WPF DataGrid is created. 

This is the comment that contains the assembly and namespace for the WPFToolkit and is incorrect. 

If you are using the WPF DataGrid tool, and want the correct comment, then please update your install of XAML Power Toys.  If not, you do not need to update.

Videos

I’m begging every developer in the strongest possible terms, please view the below videos. They will get you up and running and productive in a very short time.

The video links require Microsoft Silverlight 1.0.  If you do not have it, you will be prompted to install it when you click one of the links.  After the short installation is completed, close the browser window that you did the install in and re-click the video you want to watch.   You can also download it here. Windows XP or Vista required.

  XAML Power Toys Installation and Setup  MUST VIEW   Set Control Settings (7:13)  Please View 
  Create Business Form (5:19)   Build Form For Class (9:33)
  Edit Grid Row Columns (7:22)   Fields List For Class(6:11)
  Grid Tools (Remove Margins, Chainsaw) (5:22)   Group Into (7:28)
  Silverlight DataGrid For Class (9:53)   WPF DataGrid For Class(6:59)
  WPF ListView For Class (7:18)  

Have a great day.

Just a grain of sand on the worlds beaches.


WPF & Silverlight LOB Form Layout – Searching for a Better Solution

October 23, 2008

The only difference in these form screen shots is the applied style.

DemoTwoOneDemoTwoTwoDemoTwoThree

Simple & Clean XAML

The below XAML is almost void of layout or positioning XAML markup.  This allows almost all form layout to be controlled by applying a style; as it should be.  If I had chosen to put the header Image outside the form, there would almost be no XAML

This looks simple and clean because it is.

<pt:Form x:Name="formMain" Style="{DynamicResource standardForm}" Grid.Row="1">
      
  <pt:FormHeader>
    <pt:FormHeader.Content>
      <StackPanel Orientation="Horizontal">
        <Image Source="User.png" Width="24" Height="24" Margin="0,0,11,0" />
        <TextBlock VerticalAlignment="Center" Text="General Information" FontSize="14" />
      </StackPanel>
    </pt:FormHeader.Content>
  </pt:FormHeader>

  <TextBox pt:FormItem.LabelContent="_First Name" />
  <TextBox pt:FormItem.LabelContent="_Last Name"  />
  <TextBox pt:FormItem.LabelContent="_Phone" Width="150" HorizontalAlignment="Left" />
  <CheckBox pt:FormItem.LabelContent="Is _Active" />

</pt:Form>

Background

A month ago I was thinking about the work required to lay out a Line of Business (LOB) Application form and the maintenance of these forms.  Developer scenarios like inserting rows of controls in the middle of a large Grid layout and the extra work required to perform this task.  The work required to accomplish these everyday tasks was part of the motivation for XAML Power Toys.

In today’s WPF LOB forms the Grid is normally used for form layout.  Typically a UI control has an associated Label that is located in a nearby Grid column or Grid row. 

When a developer needs to move a UI control the corresponding Label must also be moved.  Two distinct actions are required to move both controls. 

This scenario gets more complex when attempting to move the controls using a GUI designer when the Grid rows or Grid columns have their Height or Width set to Auto.  The GUI layout engine tries its best by adding or adjusting a Margin property to maintain size and alignment.  As developers we typically then remove the designer applied Margins if our Grid sizing mode is auto. 

When laying out the form and the Grid sizing is Auto, all the rows and columns are all initially collapsed since all cells are empty.  This makes it necessary to start in the XAML editor or add sizes to Grid rows and columns until they have content.

I went home one night and wrote the Alpha version of the solution presented here.  Then Dr. WPF and I sat down together worked out some kinks and added goodness.  I spent another few hours hammering on this and wrote up the demos.

I would greatly appreciate your feedback on this blog post, especially if you are doing WPF LOB development.

Putting a Square Peg in Round Hole

The root of the problem is not the GUI designers or the WPF layout controls.

What is required is the ability to layout and move a single control that renders the UI control and corresponding Label.

Let me illustrate.  If you had a requirement to to place 7 CheckBoxes on the form, stacked up, you would add a StackPanel to the form, select the StackPanel in the WPF Designer and double click on the CheckBox control in the Toolbox 7 times, set a few properties and your done.  If you had to reorder these, it would take 1-2 seconds, done.  No fussing about.

Today we pay developers to move controls around on the screen while fighting with layout controls that were not designed to allow the simultaneous movement of two controls easily.  Our layout controls do not facilitate the laying out of controls in an Auto sized, Auto layout mode.  I think that software companies would rather have that time back so their developers can learn new technical skills like MVVM, write Unit Tests and deliver more robust applications to customers.  I’m not implying that these tasks are overly difficult, just time consuming, requiring extra steps.  It’s a simple question of economics.  How do you want your developers and designers spending their valuable time?

Solutions

We need a solution that:

  • enables RAD GUI layout and maintenance of LOB forms
  • is toolable
  • leverages the intrinsic power of WPF & Silverlight
  • can be styled
  • lays itself out
  • responds well to localization
First Choice – Enhance Existing Controls

Add a Label to all UI controls and render that Label similar to the current CheckBox.  Adding some cool properties to control placement would also be in order.  This would be a simplest solution by far.  Very easy to style and auto layout with this solution.  This solution also leverages the current layout panels, like the StackPanel enabling super fast form layout and very easy maintenance.  Code generation would be simpler and the XAML much cleaner than today’s LOB form XAML.

When I was doing ASP.NET 1.1 development, I actually subclassed every UI control that shipped in Visual Studio 2003 and added features I needed like auto layout and two-way data binding.  Another was the ability for each UI control to spit out a Label in the exact position I wanted it.  This was accomplished with CSS and it was super easy laying out ASP.NET forms without any HTML Tables, etc.  Each control, just knew how to lay itself out and render a Label.

Second Choice – New Form Control

I have not yet provided a Visual Studio 2008 design time experience for these controls but will in the next month or so.  I will add drag and drop from the Toolbox and drag and drop reordering of controls within the Form using the WPF Designer.  After I get some feedback, I’ll also add support for this control to XAML Power Toys.  For now I’ve got to finish Ocean and prepare for two Code Camps in November.

Form Control Solution Overview

The simple solution presented here consists of three UI controls; Form, FormHeader and FormItem.  These utilize WPF attached properties to control layout of child UI controls and the rendering of a Label for each child control. 

The Form control subclasses ItemsControl.  This allows me to take advantage of the built in ItemContainerGenerator to automatically wrap each child control in a FormItem control.  This is very similar to a ListBox control that automatically wraps all child controls in a ListBoxItem control.  The FormItem control provides the magic that adds the Label to the child control.  The purpose of the FormHeader control is to provide a general purpose container that will not automatically be wrapped in a FormItem control.

Form Control

FormClass

Public Class Form
  Inherits ItemsControl

  Shared Sub New()
    DefaultStyleKeyProperty.OverrideMetadata(GetType(Form), _
                                             New FrameworkPropertyMetadata(GetType(Form)))

    IsTabStopProperty.OverrideMetadata(GetType(Form), New FrameworkPropertyMetadata(False))
  End Sub

  Protected Overrides Function IsItemItsOwnContainerOverride(ByVal item As Object) As Boolean
    Return TypeOf item Is FormItem OrElse TypeOf item Is FormHeader OrElse TypeOf item Is Form
  End Function

  Protected Overrides Function GetContainerForItemOverride() As System.Windows.DependencyObject
    Return New FormItem
  End Function

End Class

The above code handles the automatic wrapping of the Form child controls in a FormItem.  The IsItemItsOwnContainerOverride method provides the developer the opportunity to make a decision to wrap the child control or not.  It would not make sense to wrap another Form, FormItem or FormHeader so we don’t.

The GetContainerForItemOverride method when overridden  provides the hook to return a special container class for the object being created.  This is the same method that many of you have overridden when customizing or extending the Menu or ListBox controls.

Also very worthy of mention is the IsTabStopProperty.OverrideMetadata in the shared constructor.  This sets the IsTabStop property on the Form to false so that the developer won’t have to.  All three of the controls presented here use this programming technique.

FormHeader

FormHeaderClass

This is a simple class that derives from ContentControl.  As mentioned above, it does not get wrapped in an FormItem control.  It exposes a Content property that allows the developer to use this any way they choose.  This control is not required, but I decided to include it in case developers wanted to section off their forms.  (See the below image of a long form that has 4 of these)

FormItem

FormItemClass

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:pt="clr-namespace:XAMLPowerToys.Controls">

  <Style TargetType="{x:Type pt:FormItem}">
    <Setter Property="Padding" Value="0" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type pt:FormItem}">
          <DockPanel Margin="{TemplateBinding Padding}">
            <Label x:Name="PART_Label" 
                   Padding="0"
                   HorizontalAlignment="Left"                   
                   HorizontalContentAlignment="{Binding 
                                            Path=(pt:FormItem.LabelHorizontalContentAlignment)}" 
                   VerticalAlignment="{Binding Path=(pt:FormItem.LabelVerticalAlignment)}" 
                   Margin="{Binding Path=(pt:FormItem.LabelPadding)}" 
                   DockPanel.Dock="{Binding Path=(pt:FormItem.LabelPosition)}" 
                   Width="{Binding Path=(pt:FormItem.LabelWidth)}" 
                   Target="{Binding}" 
                   Content="{Binding Path=(pt:FormItem.LabelContent)}" 
                   ContentTemplate="{Binding Path=(pt:FormItem.LabelContentTemplate)}" 
                   ContentTemplateSelector="{Binding 
                                            Path=(pt:FormItem.LabelContentTemplateSelector)}" />

            <ContentPresenter x:Name="PART_Control" 
                   HorizontalAlignment="{Binding Path=(pt:FormItem.ContentHorizontalAlignment)}" 
                   Margin="{Binding Path=(pt:FormItem.ContentPadding)}" 
                   Content="{TemplateBinding Content}" />

          </DockPanel>
          <ControlTemplate.Triggers>
            <Trigger SourceName="PART_Label" Property="pt:FormItem.LabelPosition" Value="Bottom">
              <Setter TargetName="PART_Control" Property="DockPanel.Dock" Value="Top" />
            </Trigger>
            <Trigger SourceName="PART_Label" Property="pt:FormItem.LabelPosition" Value="Top">
              <Setter TargetName="PART_Control" Property="DockPanel.Dock" Value="Bottom" />
            </Trigger>
            <Trigger SourceName="PART_Label" Property="pt:FormItem.LabelPosition" Value="Right">
              <Setter TargetName="PART_Control" Property="DockPanel.Dock" Value="Right" />
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

</ResourceDictionary>
#Region "LabelHorizontalContentAlignment"

  Public Shared ReadOnly LabelHorizontalContentAlignmentProperty As DependencyProperty = _
    DependencyProperty.RegisterAttached("LabelHorizontalContentAlignment", _
      GetType(HorizontalAlignment), _
      GetType(FormItem), New FrameworkPropertyMetadata(HorizontalAlignment.Left, _
      FrameworkPropertyMetadataOptions.Inherits))

  <Category("Layout")> _
  <AttachedPropertyBrowsableForType(GetType(Control))> _
  Public Shared Function GetLabelHorizontalContentAlignment( _
    ByVal d As DependencyObject) As HorizontalAlignment

    Return CType(d.GetValue(LabelHorizontalContentAlignmentProperty), HorizontalAlignment)
  End Function

  Public Shared Sub SetLabelHorizontalContentAlignment(ByVal d As DependencyObject, _
                                                       ByVal value As HorizontalAlignment)
    d.SetValue(LabelHorizontalContentAlignmentProperty, value)
  End Sub

#End Region

The FormItem derives from ContentControl.  It exposes the required attached properties to allow styling of the child controls for the purpose of automatic layout and rendering of the UI control and its corresponding Label.

The FormItem ControlTemplate is straightforward.  The DockPanel makes rendering of the Label on Top, Right, Bottom or Left of the control as easy as setting a property.  Changes to the LabelPosition attached property cause one of the ControlTemplate Triggers to fire and move the Label as directed.

When moving the Label around, the developer may also want to set the LabelHorizontalContentAlignment attached property and possibly the LabelVerticalAlignment attached property.  After investigating the control and its properties for 5 minutes you’ll figure out all the tricks this control can do and how it simplifies form layout.

I have not included all the attached property code as it’s pretty much a repeat of the above.  There are two noteworthy pieces of code in the above snippet.  First notice the FrameworkPropertyMetadataOptions.  I have this set to Inherits.  Most of the attached properties are written like this.  This is the setting that allows this attached property to get its value from another control up the Element Tree.  This is the main reason this solution is so clean.  I can set the required attached properties on the parent Form control and not have to repeat them on each individual control.  Heck, if I had multiple Form controls hosted in a Window or UserControl, I could set all the attached properties on the Window or UserControl if I wanted to.

Another possibility for setting of the attached properties is to put the settings in a style and apply it as you will see below.

The other noteworthy code is the System.Windows.AttachedPropertyBrowsableForType attribute.  When applied to an attached property and the WPF Designer selected control matches the control type assigned in the attribute, the WPF Designer Property Grid will display the attached property.  You should also apply the System.ComponentModel.Category attribute so that your attached property will displayed in desired category when the Property Grid is in category view as opposed to alpha view.

Styling Form & FormItem

<Window.Resources>
  <Style x:Key="standardForm" TargetType="{x:Type pt:Form}">
    <Setter Property="Margin" Value="11" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="BorderBrush" Value="Gray" />
    <Setter Property="Padding" Value="7" />
    <Setter Property="VerticalAlignment" Value="Top" />
    <Setter Property="HorizontalAlignment" Value="Stretch" />
    <Setter Property="Background" Value="WhiteSmoke" />
    <Setter Property="pt:FormItem.ContentHorizontalAlignment" Value="Stretch" />
    <Setter Property="pt:FormItem.LabelWidth" Value="100" />
    <Setter Property="pt:FormItem.LabelPosition" Value="Left" />
    <Setter Property="pt:FormItem.ContentPadding" Value="0" />
    <Setter Property="pt:FormItem.LabelHorizontalContentAlignment" Value="Left" />
    <Setter Property="pt:FormItem.LabelPadding" Value="0,0,0,0" />
  </Style>

  <Style BasedOn="{StaticResource standardForm}" x:Key="standardFormRightAlignedLabel" TargetType="{x:Type pt:Form}">
    <Setter Property="pt:FormItem.LabelWidth" Value="75" />
    <Setter Property="pt:FormItem.LabelHorizontalContentAlignment" Value="Right" />
    <Setter Property="pt:FormItem.LabelPadding" Value="0,0,7,0" />
  </Style>

  <Style x:Key="bottomForm" TargetType="{x:Type pt:Form}">
    <Setter Property="Margin" Value="11" />
    <Setter Property="BorderThickness" Value="3" />
    <Setter Property="BorderBrush" Value="Blue" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="VerticalAlignment" Value="Top" />
    <Setter Property="HorizontalAlignment" Value="Stretch" />
    <Setter Property="Background" Value="LightBlue" />
    <Setter Property="pt:FormItem.ContentHorizontalAlignment" Value="Stretch" />
    <Setter Property="pt:FormItem.LabelWidth" Value="100" />
    <Setter Property="pt:FormItem.LabelPosition" Value="Bottom" />
    <Setter Property="pt:FormItem.ContentPadding" Value="0" />
    <Setter Property="pt:FormItem.LabelHorizontalContentAlignment" Value="Left" />
    <Setter Property="pt:FormItem.LabelPadding" Value="0,0,0,0" />
    <Setter Property="pt:FormItem.LabelVerticalAlignment" Value="Top" />
  </Style>

  <Style TargetType="{x:Type pt:FormItem}">
    <Setter Property="Margin" Value="7,7,0,0" />
  </Style>

</Window.Resources>

Finally we can see some XAML layout markup.  I like that it’s centralized and simple.  Just by tweaking a few properties I can change the rendering of my forms.  In a production application these styles would live in the various application skin resource dictionaries or lacking skins, in application level resource dictionaries.  I also like that I can alter my form layouts without having to dig around in the XAML markup. 

Example: want more spacing between rows of controls, no problem, just look at the last style.  A single line of markup and I’m done. 

You can also see I’ve taken advantage of the BasedOn property of the second Style that allows the second style to inherit the properties of the first style and selectively modify properties.  Those of you who are familar to CSS will appreciate this super feature of WPF.

Form Control Features

DemoOne

By design, the above form does not have the separation between rows of controls like the other forms.  Also this form while not designer approved, shows off some goodness that is under the hood.

First go ahead and run the included sample application.  Tab though the form.  Notice how it just works.

Now press the <ALT> key.  This will cause the Access Key for each field to display.  Yes, I know that I have used A, C & Z twice.  I did this to illustrate different ways to wire up the Access Key.  My thanks again to Dr. WPF for showing this to me.

Below is the XAML markup for each of the addresses without the FormHeader control.

<!-- Home Address -->
<TextBox pt:FormItem.LabelContent="_Address" />
<StackPanel Orientation="Horizontal" pt:FormItem.LabelContent="City State Zip">
  <TextBox Width="150" />
  <TextBox Margin="7,0,7,0" Width="35" />
  <TextBox Width="75" />
</StackPanel>

<!-- Work Address -->
<TextBox pt:FormItem.LabelContent="_Address" />
<StackPanel Orientation="Horizontal">
  <pt:FormItem.LabelContent>
    <StackPanel Orientation="Horizontal">
      <Label Target="{Binding ElementName=txtCity}" Padding="0">_City</Label>
      <Label Target="{Binding ElementName=txtState}" Padding="3,0,3,0">_State</Label>
      <Label Target="{Binding ElementName=txtZip}" Padding="0">_Zip</Label>
    </StackPanel>
  </pt:FormItem.LabelContent>
  <TextBox x:Name="txtCity" Width="150"/>
  <TextBox x:Name="txtState" Margin="7,0,7,0" Width="35" />
  <TextBox x:Name="txtZip" Width="75" />
</StackPanel>

<!-- Vacation Address -->
<TextBox pt:FormItem.LabelContent="_Address" />
<pt:Form Margin="15,0,0,0">
  <pt:Form.ItemsPanel>
    <ItemsPanelTemplate>
      <StackPanel Orientation="Horizontal" />
    </ItemsPanelTemplate>
  </pt:Form.ItemsPanel>
  <TextBox pt:FormItem.LabelContent="_City" pt:FormItem.LabelWidth="100" Width="130" />
  <TextBox pt:FormItem.LabelContent="_State" Width="35" />
  <TextBox pt:FormItem.LabelContent="_Zip" Width="65" />
</pt:Form>

The home address does not wire up the Access Keys.  It demonstrates one way to utilize a StackPanel to render controls horizontally.

The work address shows how to customize the LabelContent property of a child control (in this case a StackPanel) and insert a StackPanel that contains Labels that are associated with TextBoxes.  These Labels have their Access Keys set.

The vacation address is displayed in a nested Form control that has its ItemsPanel set to a StackPanel with Horizontal Orientation.

Downloads

After downloading the below package, you must rename it from .doc to .zip.  This is a requirement of WordPress.com

Download Source 52KB

Close

I think this solution, a similar or better one, will help all of us when developing and maintaining our WPF & Silverlight LOB applications.  In addition developers transitioning from Win Forms will find a friendly and very productive environment awaiting them. 

Please leave both positive and negative feedback on the two solutions proposed here.  Do you have another solution?  Please blog it and send me the link.

Have a great day!

Just a grain of sand on the worlds beaches.


Super Tip For XAML Power Toys

October 19, 2008

I received an email today from Ruurd Boeke telling me about a very cool Visual Studio Macro he wrote to quickly and efficiently select a control and all it’s children in the XAML editor.

This is a great tip for XAML Power Toys users.  In the past I had suggested collapsing a control and children by using the (+) (-) icons.

I followed the directions on his blog post, Macro For Quickly Selecting A Complete XAML Tag and was up and running in minutes.  This macro is the bomb for selecting this large Grids in our XAML.

Hope you enjoy XAML Power Toys!

Have a great day!

Just a grain of sand on the worlds beaches.


XAML Power Toys 3.3 Released With New Class Browser

October 14, 2008

XAML Power Toys is a multi-AppDomain Visual Studio Add-In for WPF and Silverlight developers that provides features to Visual Studio to enhance the XAML editing experience and the laying out of forms, DataGrids, ListViews.

I have updated the XAML Power Toy Home Page with the latest source, installers, documentation and of course a video covering the new features in v3.3.

This version of XAML Power Toys is compatible with Silverlight 2.0 RTM.

New Features In v3.3

You can now select a class by using a class selector;  see image below.  You open the class selector by right-clicking in the XAML editor.  This is supported for the “Form, ListView, DataGrid” command and the “Field List” command.  In previous versions you were limited to right clicking on a file in the solution explorer.  If that file had two classes, it would only select the class with a matching name.  This feature also allows selecting classes in referenced assemblies that you may not have the source file to click on.

Added the Change Grid To Flow Layout command.  This is very similar to the Chainsaw except it does not remove the x:Name or Name properties.

Fields List enhanced again.  You can now select to include the Grid.Column and Grid.Row attached properties if you’ll be dragging the field into a Grid.  This just save you from typing them.

v33SelectClass

Get It Now!

Visit the XAML Power Toy Home Page and get all the newest goodness!

Have a great day.

Just a grain of sand on the worlds beaches.


Viewing Design Time Data in Visual Studio 2008 Cider Designer in WPF and Silverlight Projects

October 11, 2008
SilverlightOne

“I did this ListBox DataTemplate layout in a fraction of the time because I didn’t have to re-run my project between edits to see the results.

I could see the changes on the Cider design surface as I was editing the template XAML.”

They say a picture is worth a thousand words.  I’m sure the above picture certainly got your attention.  Let’s understand how you can do this in a few minutes in your projects TODAY.

This simple solution significantly raises the productivity bar when working with DataTemplates, DataGrids, ListBoxes or ListViews because the Cider Designer will simply re-render as you edit the XAML.

You no longer have to keep running the project and tweaking between runs, just follow these super simple instructions and the Cider Designer will be your new best friend.  This solution works in WPF and Silverlight TODAY.

Background

I came into work earlier this week and mentioned to Mark Boulter a Microsoft Principal Program Manager Lead on the Cider Team that I was working on a complex ComboBox DataTemplate the previous night and I wished that I could have accomplished the task with design time data displayed in the Cider Designer.  That this would have made the DataTemplate editing task much easier for me.

He just came out and said, “you can.”  Most of you that know me, can picture Karl’s ears perking up and an above indoor voice replying with excitement, “what!”

There is no magic, no monkey business going on.  The Visual Studio 2008 Cider Designer instantiates controls and renders them on the design surface.  If that control has a DataContext with data in it and the control is data bound, the data displays.  It’s that simple.

I’m not sure why this light did not come on in my brain before.  Of course Cider instantiates controls.  It has to so that it can render the control properly when properties like Background and Width are set on the control.  This is why all controls must have a default empty constructor, so that they can be instantiated by the designer.

So with 5 minutes of brain storming and 15 minutes of trail and error coding, Mark, Ben and I came up with the solution that is being presenting here.  Ben Wulfe is a Microsoft Senior Software Development Engineer on the Cider Team.

We sincerely hope you find this solution easy to use and that you get a greater design time experience by using it.

So as many of my super geek friends would say, “let’s feel the love and write some code!”

The Data

WPFOne

SilverlightThree

The Customer class is a from the WPF project and is your typical WPF business entity object.  Customers represents the collection of Customer.  These are similar to your standard classes already in your current WPF and Silverlight projects.

The DesignTimeCustomers class provides the Cider Designer the design time data.  Rather than create a special design time data class with the same shape as Customer and Customers, I chose to derive from Customers.  Now I’m guaranteed that any breaking changes to Customers or Customer will cause a compile time error and I can quickly resolve the issue.

I’ve also placed DesignTimeCustomers in its own Namespace to avoid any problems on large projects like a developer using a design time class instead of a real run-time class.

Now for the secret sauce.  By loading the individual Customer objects into the DesignTimeCustomers collection in the constructor, I have a class that when instantiated will be a class with its collection fully populated and ready to be consumed, even at design time.

Namespace DesignTimeData

    Public Class DesignTimeCustomers
        Inherits Customers

        Public Sub New()
            Me.Add(New Customer(True, 55000, 1, "Tim", "Smith"))
            Me.Add(New Customer(True, 75000, 2, "John", "Johnson"))
            Me.Add(New Customer(True, 52000, 3, "Susan", "Washington"))
        End Sub

    End Class

End Namespace

For each of the DataTemplates, DataGrids, ListBoxes, ListViews or ComboBoxes you need design time data viewing, you’ll create a class similar to the above.  I was thinking about writing and Add-In that creates these classes but that’s for another day.

The Resource

This solution has two methods of implementation.

  • Solution One:  Design Time and Run-Time DataContext – you assign the DataContext to a resource that points to the above DesignTimeCustomers
  • Solution Two:  Different Design Time and Run-Time DataContext – using the DesignAndRunTimeDataContext class allows specifying both a design time and run-time DataContext.  This provides the ability to consume the above DesignTimeCustomers class at design time and when the project is run, the DataContext can be set in code, displaying records from a data base for example.  This class only works in WPF because Silverlight does not have a DataSourceProvider class which is what DesignAndRunTimeDataContext derives from.

I think implementation comes down to each developer’s workflow.  If you want automatic design time and run-time DataContext switching, use the second solution above.  Otherwise use the first solution.

Solution One
<UserControl 
    x:Class="SilverlightTestingDesignTimeData.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:DesignTimeData="clr-namespace:SilverlightTestingDesignTimeData.DesignTimeData"         
    Width="325" Height="200">
    
    <UserControl.Resources>
        <DesignTimeData:DesignTimeCustomers x:Key="designTimeCustomersDS" />
    </UserControl.Resources>

The above code snippet is from the Silverlight demo project included in the project downloads.  I’ve just created a resource that points to the above DesignTimeCustomers class.  The resource will be instantiated by the Cider Designer at design time.  Since the collection is populated in its constructor, we now have a populated collection that can be consumed at design time.  How cool is that!

Solution Two

Solution two can be implement one or more ways also.

Below the DesignTimeDataContext and the RunTimeDataContext have both been assigned to the same resource.  I did this to keep the example as simple as possible.  If I had a resource that pointed to another collection at run-time I could have used it.

Don’t forget to add the namespace declaration for DesignTimeData.

<Window 
    x:Class="DesignTimeDataTwo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:DesignTimeData="clr-namespace:VisualStudio2008DesignTimeData.DesignTimeData" 
    xmlns:local="clr-namespace:VisualStudio2008DesignTimeData"
    Title="Design Time Data Demo Two" Height="300" Width="300">
    <Window.Resources>
        
        <DesignTimeData:DesignTimeCustomers x:Key="designTimeCustomersDS" />
        
        <local:DesignAndRunTimeDataContext 
            x:Key="customersDS"
            DesignTimeDataContext="{StaticResource designTimeCustomersDS}" 
            RuntimeDataContext="{StaticResource designTimeCustomersDS}" />

    </Window.Resources>

In the below code the DesignTimeDataContext is being set in XAML and the RunTimeDataContext is being set in the code behind file at run-time.

<Window 
    x:Class="DesignTimeDataTwo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:DesignTimeData="clr-namespace:VisualStudio2008DesignTimeData.DesignTimeData" 
    xmlns:local="clr-namespace:VisualStudio2008DesignTimeData"
    Title="Design Time Data Demo Two" Height="300" Width="300">
    <Window.Resources>
        
        <DesignTimeData:DesignTimeCustomers x:Key="designTimeCustomersDS" />
        
        <local:DesignAndRunTimeDataContext 
            x:Key="customersDS"
            DesignTimeDataContext="{StaticResource designTimeCustomersDS}" /> 

    </Window.Resources>

At run-time when the Window loads the below code assigns run-time data to the RunTimeDataContext property and then the DesignAndRunTimeDataContext.Refresh method is called which will cause this custom DataSourceProvider to re-query its data.  You can have a look at the DesignAndRunTimeDataContext class in the WPF project included in the downloads below.  Its a very simple class that provides DataContext switching between design time and run-time.

Partial Public Class DesignTimeDataTwo

    Private Sub DesignTimeDataTwo_Loaded( _
            ByVal sender As Object, _
            ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim objDS As DesignAndRunTimeDataContext = _
            CType(Me.FindResource("customersDS"), DesignAndRunTimeDataContext)

        'could load any data here, I'm just using what we have for grins
        objDS.RuntimeDataContext = New DesignTimeData.DesignTimeCustomers

        objDS.Refresh()

    End Sub

End Class

The DataContext

Wiring up the DataContext to the above resource is very simple.  The ListBoxes ItemsSource property is also set and the ListBox performs a data binding operation at design time.

<Grid DataContext="{StaticResource customersDS}" >
    <ListBox x:Name="lbCustomer" ItemsSource="{Binding}">

Data Triggers

After I did the video, I got to thinking about Data Triggers, so I wrote this simple Data Trigger to see if the Cider Designer would render it or not.  Oh yes!  It works great!

<DataTemplate.Triggers>
    <DataTrigger Binding="{Binding Path=Id}" Value="1">
        <Setter TargetName="tbId" Property="Foreground" Value="Red" />
    </DataTrigger>
</DataTemplate.Triggers>

Look close at the below image, notice that the Id for the first row has a Foreground of Red.  This should give you enough to go with and learn to use the Data Triggers in your Data Templates.

WPFTwo

Actual Usage

Don’t forget to build your projects after editing the entity classes.

I have seen an error sometimes when working with this solution in Silverlight projects.  If you get an error when loading the designer, just leave the designer displayed and rebuild the project; the Cider Designer will correctly render your UserControl content.

Blend Compatibility

Guess I really don’t need to say much.  Here is Blend 2 with Blend SP1 applied editing a ListBox DataTemplate with design time data using this solution.  You can read about the latest Blend releases on Scott Guthrie’s blog.

BlendToo

After I posted this solution my friend and Microsoft MVP Laurent Bugnion wrote me about a solution he came up with last year that focuses on Blend.

Here is the link to his article:

http://blog.galasoft.ch/archive/2007/09/14/WPF-Simulating-data-in-design-mode-in-Microsoft-Expression-Blend.aspx

Also of interest, he has a sample WPF application demonstrating this technique:

http://blog.galasoft.ch/archive/2008/03/27/techdays-2008-slides-and-code-of-my-presentation-available-online.aspx

Thanks Laurnet!

Let’s Go!

Mark, Ben and I hope this simple solution provides each Visual Studio 2008 WPF & Silverlight developer a boost in design time productivity using the Cider Designer.  I don’t know about you, but I’m so juiced over this and now look forward to that next complex DataTemplate or DataGrid layout task!

Videos

The video links require Microsoft Silverlight 1.0.  If you do not have it, you will be prompted to install it when you click one of the links.  After the short installation is completed, close the browser window that you did the install in and re-click the video you want to watch.   You can also download it here. Windows XP or Vista required.

  Design Time Data Tutorial (only 5:46 long)

Downloads

After downloading the below package you must rename the extension from .DOC to .zip.  This is a requirement of WordPress.com.

Download Source WPF Project 279KB

Download Silverlight Source 548KB

Have a great day and feel the love!

Just a grain of sand on the worlds beaches.


XAML Power Toys 3.1.0.2 Has Silverlight 2 Support!

October 5, 2008

On Friday night I lit my hair on fire cranked up the jams and spent the weekend adding full support for Silverlight 2 RC0 to XAML Power Toys. 

XAML Power Toys is a multi-AppDomain Visual Studio Add-In for WPF and Silverlight developers that provides features to Visual Studio to enhance the XAML editing experience and the laying out of forms, DataGrids, ListViews.

I have updated the XAML Power Toy Home Page with the latest source, installers, documentation and of course videos! 

Silverlight developers you will want to watch at least two of the video on the XAML Power Toys home page; Installation and Setup and the Silverlight Features.  This will help you get up and running real fast and visually see how productive you will become when your toolbox has XAML Power Toys in it.

Current XAML Power Toys Users

Current XAML Power Toys users, please upgrade even if you are not a Silverlight developer.  I have made many fixes and corrected things I didn’t like and increased stability even more.

WPF developers, you do not have to install the Silverlight RC0 bits if you don’t want to.  The only reason for installing Silverlight RC0 is so that you can do Silverlight development prior to the RTM and because the XAML spit for Silverlight projects is RC0 compliant.

All Developers

This week Pete O’Hanlon will be posting a complete walk through for using his MO XAML Power Tools Add-In to very quickly create Silverlight friendly business object and then use XAML Power Toys to lay it out.  Thanks Pete for doing this!

Get It Now!

Visit the XAML Power Toy Home Page and get all the newest goodness!

Have a great day.

Just a grain of sand on the worlds beaches.


Follow

Get every new post delivered to your Inbox.

Join 241 other followers