Welcome to MSDN Blogs Sign in | Join | Help

WPF & Silverlight Designer

The Visual Designer for creating WPF & Silverlight applications in Visual Studio
Known Issue: Second Hot Fix Available for Visual Studio 2010 Release Candidate Crash

A second hot fix has been made available for Visual Studio 2010 Release Candidate that solves another IntelliSense related crash.

Get the hot fix Information here.

There are now two hot fixes.  Please ensure that if you are using Visual Studio 2010 Release Candidate that you install both hot fixes.

First Hot Fix

Second Hot Fix

We apologize for this inconvenience.

Have a great day,

Karl Shifflett
Visual Studio Cider Team

Known Issues for Visual Studio 2010 Release Candidate

This post provides information on a few high profile Visual Studio 2010 Release Candidate bugs and some additional information that will help developers have a successful experience with the WPF & Silverlight Designer.

Known Issues

Visual Studio crashes when IntelliSense displays

Problem: Users have reported frequent crashes of Visual Studio 2010 Release Candidate when IntelliSense displays.  This can happen in the XAML Editor or Code Editor.

Solution: If you are experiencing crashes please install this Hot Fix: http://code.msdn.microsoft.com/KB980610

Find in Files is very slow when the XAML Editor is open

Problem: Some customers have reported that the Find if Files feature of Visual Studio can by very slow if a XAML Editor document is open and the search is conducted shortly after opening the solution.

Solution: If this bug affects your work, close all Visual Studio documents and then close Visual Studio. Reopen Visual Studio and the solution you were working on. Before opening any documents, perform the Find in Files search.

This bug will be corrected for the final release of Visual Studio 2010.

Implicit Style using BasedOn Disables the Designer

Problem: If you have an implicit Style that uses BaseOn that is located in App.xaml or in a Merged Resource Dictionary that is merged in App.xaml, the WPF & Silverlight Designer will always be in a read-only error state.

Gold Bar Error: InstanceBuilderException was thrown due to a document error: a loop was detected in the property expressions

Error List Error: A loop was detected in the property expressions

Solutions

  • Use full XAML View or edit XAML files with the Source Code (Text Editor) rather than use the Designer.
  • Instead of merging resource dictionaries in App.xaml, merge them in the root Window or root UserControl as below.  The below solution while less than ideal, will enable using the Designer along with BaseOn styles in Resource Dictionaries.

Dictionary1.xaml content – note BaseOn Style

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="Background" Value="Green" />
        <Setter Property="Foreground" Value="Yellow" />
    </Style>

</ResourceDictionary>

MainWindow.xaml – note Dictionary1.xaml was merged here, rather than App.xaml.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary1.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
    <Grid>
        
        <TextBlock Text="Hello" />
        
    </Grid>
</Window>

Application Compatibility

Silverlight Support for Visual Studio 2010 Release Candidate

Silverlight 3 projects are supported with the Visual Studio 2010 Release Candidate build – however Silverlight 4 projects are not yet supported.

We will be adding Visual Studio 2010 Release Candidate support for Silverlight 4 with the next public Silverlight 4 drop.

If you are doing active Silverlight 4 development today we recommend staying with the Visual Studio 2010 Beta 2 build for now.

Tim Heuer has also blogged about this limitation here.

No Expression Blend Support for .NET 4.0 Projects

Expression Blend does not support for .NET 4.0 projects.  

Visual Studio 2010 Release Candidate customers can use Blend to target .NET 3.5 and SL3, but not .NET 4.0.

Designer Limitations

Custom MarkupExtensions should be located in a separate assembly

Developers writing their own MarkupExtensions should locate them in a separate assembly from the assembly that is consuming them for the best design support.  If located in the same assembly the following error may be displayed:

Error Message:  No constructor for type '[ClassName]' has 0 parameters

Image files with Build Action set to Content work at runtime but not at design time for Silverlight

Usually, Silverlight image files have their Build Action set to Resource.  The Silverlight run-time supports setting the Build Action to Content.  However the Designer will display the following gold bar error:

Error Message:  Project does not support paths relative to the root application directory.

Unhandled design-time exceptions in Converters and DataTemplateSelectors

At design-time, the Designer executes code in Converters and DataTemplateSelectors.  If those classes allow an unhandled exception to bubble up to the Designer, an exception will be displayed in the Designer.

Developers must ensure they code defensively to avoid this design-time problem.

Known Issue: Hot Fix Available for Visual Studio 2010 Release Candidate Crash

If you have installed Visual Studio 2010 Release Candidate and have experienced one or more crashes while editing Code or XAML please install the below hot fix.  The crashes are related to IntelliSense displaying.

Hot Fix:  http://code.msdn.microsoft.com/KB980610

We apologize for this inconvenience.

Have a great day,

Karl Shifflett
Visual Studio Cider Team

Silverlight Support for Visual Studio 2010 Release Candidate

Silverlight 3 projects are supported with the Visual Studio 2010 Release Candidate build – however Silverlight 4 projects are not yet supported.

We will be adding Visual Studio 2010 Release Candidate support for Silverlight 4 with the next public Silverlight 4 drop.

If you are doing active Silverlight 4 development today we recommend staying with the Visual Studio 2010 Beta 2 build for now.

Tim Heuer has also blogged about this limitation here.

Have a great day,

Karl Shifflett
Visual Studio Cider Team

Loading Projects in Visual Studio not Located on Local Machine

The new boot from vhd feature that shipped in Windows 7 and Server 2008 has now given developers new options for setting up a test systems with different versions of Visual Studio.

For the purpose of this post, local system is the vhd boot volume and host system is the operating system and its drives that the vhd is physically located on.

Some developers are booting into their vhd, then accessing source projects that are actually located on the host system or are trying to load projects located on the network.

We recommend that projects be located on the local system.  However, if your scenario requires that you load projects not located on the local system, the following steps can be taken to enable this scenario.

Network Share

If you must use a project on a network share, map the network share to a local drive rather than trying to use UNC path similar to the below example. 

Example:   Map \\systemName\pathName to e:\shareName.

loadFromRemoteSources

The loadFromRemoteSources option is available to enable assemblies being loaded from remote sources to be loaded as full trust. 

Please ensure that you read the MSDN loadFromRemoteSources topic and are fully aware of the implications of using this setting.  The MSDN topic has instructions for enabling this setting.

If you have Visual Studio 2010 installed on a vhd, and your source projects are located on the host system or network drive, you’ll need to use the loadFromRemoteSources setting to enable this scenario.

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Known Issue: Attached Property ListBox.AlternationIndex Causes Error in Designer

Known Issue

When writing ListBoxItem triggers in a style that trigger on the ListBox.AlternationIndex attached property value, if you use the valid syntax ListBox.AlternationIndex like the first trigger below, the designer will display the following error:

Error Property 'AlternationIndex' was not found in type 'ListBox'… 

Workaround

The workaround is to use the alternate valid syntax  ItemsControl.AlternationIndex as the second trigger below does.

<Style x:Key="alternatingWithTriggers" TargetType="{x:Type ListBoxItem}">
  <Setter Property="Background" Value="Blue"/>
  <Setter Property="Foreground" Value="White"/>
  <Style.Triggers>
    <!-- valid XAML but does not work in the designer and causes an error -->
    <Trigger Property="ListBox.AlternationIndex" Value="1">
      <Setter Property="Background" Value="CornflowerBlue"/>
      <Setter Property="Foreground" Value="Black"/>
    </Trigger>

    <!-- valid alternate XAML that works in the designer -->
    <Trigger Property="ItemsControl.AlternationIndex" Value="2">
      <Setter Property="Background" Value="LightBlue"/>
      <Setter Property="Foreground" Value="Navy"/>
    </Trigger>
  </Style.Triggers>
</Style>

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Taming the WPF Expander Control

The WPF Expander control has a header and a collapsible window that developers can use in several different ways.  One technique is to place multiple Expander controls in a StackPanel to create a UI region of expanding sections,  Another technique is to use the Expander as a way of hiding less important information on the UI, creating an on-demand region for the end user to view if needed.  Outlook uses an Expander to provide the UI for its query builder.  A while back, I wrote about a technique for having the Expander control popup overtop of other controls without moving them in this blog post.

This short post will help you to have a successful experience with the Expander control at design-time and run-time.

tamingtheexpander 

Adding an Expander to the Design Surface

When you drag and drop an Expander control from the Toolbox to the design surface the below XAML will be created for you.

<Expander Grid.Column="1" Grid.Row="2" Header="expander3" Height="100" HorizontalAlignment="Left" 
          Margin="25,25,0,0" Name="expander3" VerticalAlignment="Top">
  <Grid />
</Expander>

If you look at the above image, you’ll notice some expanders have been named, “Has Layout Problem.”  The above default XAML actually causes the layout problem because the Expander control has been assigned Height property.

Below is an Expander with the Height set to auto (Height removed) and the inner child Grid Height set to 100.  The inner child Grid will be displayed when the Expander is expanded.  This Expander will not have any design-time issues.

<Expander Panel.ZIndex="99" Header="No Layout Problems" HorizontalAlignment="Left" 
          Margin="17,7,0,0" Name="expander2" VerticalAlignment="Top" Width="225" 
          Grid.Column="1" Grid.Row="2">
  <Grid Background="Maroon" Height="100" />
</Expander>

Stacked Expanders

If you look at stacked Expanders in the above image you’ll notice the bottom two Expanders are taking up much more vertical space than the top two Expanders even though all four Expanders are in a collapsed state.  This is because the the bottom two expanders have their Height set on the Expander control and not the inner child Grid.

The below image pictures the desired Expander design-time experience.  When the Expander is selected on the design surface, it expands, exposing the inner child Grid that can now be designed.  Controls can be dragged to it from the Toolbox, etc.

However, if you want to drag another control from the design surface to the Expander, a slightly different technique is required.  When you select any control not inside the Expander, the Expander will close.  To drag another control into the Expander, select the other control, dragging the mouse over the header portion of the Expander and the Expander will automatically expand for you so you can drop your control as required.

stackedexpanderexpanded

Data Form Example

beforeafterclick

The above image shows what happens when the two TextBoxes are selected on the design surface.

When the TextBox below the No Layout Problems Expander is clicked (first column), normal control selection takes place.

When the TextBox below the Has Layout Problem Expander is clicked (third column), the Expander expands and the Expander’s child Grid is selected and not the TextBox.  This occurs because the mouse is performing an action within the Expanders region.  In reality the Expander is actually doing what it is supposed to do.

Since the lower Expander in column 3 and 4 has a height of 100, when any control is dragged or clicked within the Expanders size, the Expander expands.  This is the same behavior we had above when the Expander had an Auto Sized Height, except the region that triggers the auto expansion was much smaller and did not interfere with other design-time gestures.

Solution

Setting the Expander control’s Height to Auto will provide the best design-time experience.  The height of the Expander will then be determined by the content of the Expander’s Header.

The inner child Grid (or other Panel or control) can either be Auto Sized or have a fixed size.  However, if the inner child Grid is Auto Sized and does not have any content, its design-time size will be very small until child controls are added.

You can download the above sample solution using the link at the bottom of this post.

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Known Issue: Controls and GAC, Toolbox and TCI

Introduction

The purpose of the post is to provide guidance for control authors to limit the controls added to the Toolbox and that are listed in the Choose Items Dialog.

The word "controls" in this post is defined as "any public type in a control assembly that derives from FrameworkElement or above." Both the TCI and Choose Items Dialog include all public types that derive from FrameworkElement or above.

Does This Information Apply To My Control Assemblies?

If your control assemblies are installed in the GAC and you want to limit controls visible in the Choose Items Dialog you must follow the guidance in this post.

If you use the TCI to have Visual Studio install your controls in the Toolbox and you install your control assemblies in the GAC and want to limit controls installed into the Toolbox and controls visible in the Choose Items Dialog you must follow the guidance in this post.

If you use the TCI to have Visual Studio install your controls in the Toolbox, you must have a design-time assembly to limit controls installed in the Toolbox. This applies to both WPF & Silverlight controls.

This post covers two known issues.

  • WPF only. Public types in control assemblies installed in the GAC that derive from FrameworkElement or above are now required to be decorated with the System.ComponentModel.DesignTimeVisible(false) attribute in order to keep the type from appearing in the Toolbox or the Choose Items Dialog. Not decorating the type with this attribute, could result in the type being added to the Toolbox and will result in the type being listed in the Choose Items Dialog.
  • WPF and Silverlight. Control assemblies that are installed using the TCI require a design-time assembly to limit the types added to the Toolbox and the Choose Items Dialog. Without the design-time assembly, all types deriving from FrameworkElement or above will be placed in the Toolbox and will be listed in the Choose Items Dialog.
Critical

If a control assembly is installed into the GAC and uses the TCI, you must implement both of the above steps to keep unwanted types out of the Toolbox and Choose Items.

Scenario Assemblies

The following two WPF assemblies are assumed for this post.

  • C:\Acme\Acme.Controls.dll
  • C:\Acme\Acme.Controls.Design.dll

Acme.Controls.dll

Each of the below four custom controls has a two line summary comment.  The first line of the comment describes what if any metadata is associated with the control in the design assembly.  The second line applies to the control itself.  The name of the control describes when the control will be visible.

namespace Acme.Controls {

    /// <summary>
    /// This control has a design assembly ToolboxBrowsableAttribute false.
    /// This attribute only gets processed when this assembly is in the GAC.
    /// </summary>
    [DesignTimeVisible(false)]
    public class YouShouldNeverSeeMe : Control {
    }

    /// <summary>
    /// This control has a design assembly ToolboxBrowsableAttribute true.
    /// This control will be in the Toolbox and Choose Items.
    /// </summary>
    public class ToolboxBrowsableAttributeTrue : Control {
    }

    /// <summary>
    /// This control has a design assembly ToolboxBrowsableAttribute false.
    /// This control will not be in the Toolbox or Choose Items unless this assembly is loaded in the GAC.
    /// </summary>
    public class OnlyShowsInChooseItemsWhenInGAC : Control {
    }

    /// <summary>
    /// This control does NOT have a design assembly ToolboxBrowsableAttribute.
    /// WARNING:  This control will always be loaded in the Toolbox and will be visible in Choose Items.
    /// </summary>
    public class FrameworkElementAlwaysShows : FrameworkElement {
    }
}

Acme.Controls.Design.dll

The below design assembly applies to the above control assembly.

The ToolboxBrowsableAttribute can be created two ways, both syntaxs create the required attribute:

//This should be in AssemblyInfo.cs - declaring here to make it obvious
//This attribute is used to determine which class to load to register metadata
[assembly: ProvideMetadata(typeof(Acme.Controls.Design.RegisterMetadata))]

namespace Acme.Controls.Design {

    internal class RegisterMetadata : IProvideAttributeTable {

        public Microsoft.Windows.Design.Metadata.AttributeTable AttributeTable {
            get {
                AcmeControlsAttributeTableBuilder obj = new AcmeControlsAttributeTableBuilder();
                return obj.CreateTable();
            }
        }
    }

    class AcmeControlsAttributeTableBuilder : AttributeTableBuilder {

        public AcmeControlsAttributeTableBuilder() {
            AddTypeAttributes(typeof(ToolboxBrowsableAttributeTrue), ToolboxBrowsableAttribute.Yes);
            AddTypeAttributes(typeof(OnlyShowsInChooseItemsWhenInGAC), ToolboxBrowsableAttribute.No);
            AddTypeAttributes(typeof(YouShouldNeverSeeMe), ToolboxBrowsableAttribute.No);
        }
        
        void AddTypeAttributes(Type type, params Attribute[] attribs) {
            base.AddCallback(type, builder => builder.AddCustomAttributes(attribs));
        }
    }
}

Scenario: TCI Toolbox Install

AssemblyFoldersEx Registry Entry

The following two registry entries will install the controls into the Toolbox under the Acme Toolbox tab.

[HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0\AssemblyFoldersEx\Acme]

@="c:\\Acme\\"

[HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0\AssemblyFoldersEx\Acme\Toolbox]

TabName="Acme"

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is Not in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it. 

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it.

In the control assembly, decorate public types with the DesignTimeVisible(false)attribute to hide it.

Scenario: No TCI, Just Choose Items Dialog

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is Not in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it.

How to Limit Types in the Toolbox and Choose Items Dialog when the Assembly is in the GAC

In the design assembly, add the ToolboxBrowsableAttribute.No to a public control assembly type's metadata to hide it.

In the control assembly, decorate public types with the DesignTimeVisible(false)attribute to hide it.

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Known Issue – Controls Deriving From A Generic Base Class Must Be In Separate Assembly

There is a known issue when using the Visual Studio 2010 WPF & Silverlight Designer or XAML Editor and a control derives from a generic base class.  The control and generic base class must be located in separate assemblies, otherwise the Designer and XAML Editor will display the following error:

Error 1 The type 'local:GenericBase' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built

The listed error will not prevent you from using the Designer or building your application.  However, its a misleading error message that does not help you correct the design-time problem.

Workaround

To workaround this issue, you’ll need to place the generic base class in a separate assembly from the control as pictured below.

In this example the UserControlWithGenericBase derives from GenericBase and the two types are located in separate assemblies.

solutionexplorer classdiagram

TypeArguments Property

In the above class diagram you can see that UserControlWithGenericBase derives from:

  • C#  GenericBase<String> 
  • VB – GenericBase(Of String)

Notice the third line of XAML, the x:TypeArguments property is set to sys:String.  This matches the generic type argument passed to GenericBase in the above class diagram and the UserControlWithGenericBase UserControl class declaration below.

x:TypeArguments is required when the base class is a generic type.

<gbc:GenericBase
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    x:TypeArguments="sys:String"
    xmlns:gbc="clr-namespace:GenericBaseClassLibrary;assembly=GenericBaseClassLibrary"
    x:Class="UserControlDerivingFromGenericTypeCS.UserControlWithGenericBase"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300">

    <Grid>
    </Grid>

</gbc:GenericBase>

C# Code

public partial class UserControlWithGenericBase : GenericBase<String> {
    public UserControlWithGenericBase() {
        InitializeComponent();
    }
}

VB.NET Code

Public Class UserControlWithGenericBase
    Inherits GenericBase(Of String)
End Class

Silverlight

This workaround only applies to WPF applications.  Currently Silverlight does not support the x:TypeArguments property that is required in the deriving control’s XAML root tag.

If you must have Silverlight controls that derive from a generic base class you have to do some extra work.  Basically you need to have an extra class in the middle so that the UserControl would derive from a non-generic class

Base class:  public class GenericBase<T> : UserControl

Middle class:  public class MiddleStringControl : GenericBase<String>

UserControl:  public class UserControlWithGenericBase : MiddleStringControl

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above feature enables your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Create WPF Master – Detail UI Using Data Sources Window Object DataSource

Master – Detail layouts are the bread and butter of Line of Business (LOB) applications. This walkthrough will show you how to drag & drop from the Data Sources Window to create the UI that is sourced from an Object DataSource.

This article has a C# and VB.NET download that includes both a completed solution and a starter solution. The starter solution includes the data entity classes and a static (Shared) data source class.

This walkthrough assumes that you'll be starting with the starter solution.

Completed Application

Figure 1 Completed Application

Starter Solution

Open the accompanying (C# or VB.NET) starter solution.

Figure 2 Starter Solution

The Data class provides two static (Shared) properties that expose an ObserveableCollection that the application will use as its data source. The Data class takes the place of a data layer that would be used to populate CLR classes from a database.

Figure 3 Data Class Diagram

The Customer class can contain one or more Addresses. Each Address has an associated AddressType.

Figure 4 Entity Class Diagram

Adding a Title to the Form

Step One

Figure 5 Draw Border

  • Build the solution
  • Open ApplicationMainWindow.xaml
  • Select the root Grid by clicking inside the Window
  • Create a new Grid Row that takes up about 25% of the Window by
    • Click the Grid rail on the left to create a new row
  • Draw a Border control inside the new row
    • Select the Border control in the Toolbox then draw the Border as pictured in Figure 5 above

Step Two

  • Draw a TextBlock control inside the Border
  • Multi-select the TextBlock and Border controls using either the Document Outline or by CTRL + clicking each control
    • Right click, select Reset Layout, All
    • This will reset the Width, Height, HorizontalAlignment and VerticalAlignment properties to their default values

 ResetBorderTextBlockLayout

Figure 6 Reseting Values

  • After properties are reset your Window should look like Figure 7 below

Figure 7 Title Step Two

Step Three

  • Using the Document Outline, select the Border control
  • Using the Properties Window set the following properties:
    • CornerRadius to 30
    • Margin to 11
    • Padding to 7
    • BorderThickness to 2
    • Background to formTitleBackgroundBrush
      • Use Resource Picker, see Figure 8 below.  After opening Resource Picker, select formTitleBackgroundBrush.
    • BorderBrush to formTitleBorderBrush
      • Use Resource Picker, see Figure 8 below.  After opening Resource Picker, select formTitleBorderBrush.

    Figure 8 Applying Resource

  • Using the Document Outline, select the TextBlock
  • Using the Properties Window set the following properties
    • Text to Customer
    • VerticalAlignment to Center
    • FontSize to 18
    • FontWeight to Bold
    • Foreground to formTitleForegroundBrush
      • Use Resource Picker
  • Select the Grid
  • Hover cursor over the left Grid rail for the top row. Set top row to Auto sizing as in Figure 9 below
  • The bottom image in Figure 9 shows the completed form title

Figure 9 Auto Sizing Row

Adding the ComboBox Used for Record Selection

Step One

  • Select the root Grid by clicking inside the Window
  • Create a new Grid Row that takes up about 25% of the Window
    • Click the Grid rail on the left to create a new row
  • Draw a StackPanel inside the new row
  • Add a TextBlock to the StackPanel by double clicking the TextBlock icon in the Toolbox
  • Add a ComboBox to the StackPanel by double clicking the ComboBox icon in the Toolbox
  • Form should now look like Figure 10 below

Figure 10 StackPanel

Step Two

  • Select the StackPanel
  • Right click on the StackPanel, choose Reset Layout, All
  • Using the Properties Window set the following properties:
    • Margin to 11
    • Orientation to Horizontal
  • Multi-select the TextBlock and ComboBox
  • Right click on the TextBlock and choose Reset Layout, All
  • Using the Properties Window set the following property:
    • VerticalAlignment to Center
  • Form should now look like Figure 11 below

    Figure 11 StackPanel

Step Three

  • Select the TextBlock
  • Using the Properties Window set the Text property to Select Customer
  • Select the ComboBox
  • Using the Properties Window set the following properties:
    • Margin to 7, 0
    • Width to 175
  • Form should now look like Figure 12 below

    Figure 12 Record Selector Completed

Step Four

From the Data menu, select Show Data Sources.

Figure 13 Data Menu

Figure 14 Data Sources Window

Important

Before clicking the Add New Data Source link, you must have built your solution.  The Data Sources Window uses reflection to discover types in your solution.  If the type has not been built yet, it will not appear in the Data Sources Window.



  • Add a new Data Source by clicking on the "Add New Data Source…" link pictured in Figure 14 above
  • When the Data Source Configuration Wizard is displayed select the Object icon and click the Next button

Figure 15 Select Data Objects

  • Drill down to the Customer object and select it, then press the Finish button
  • Figure 16 below shows the newly created Object Data Source

Figure 16 New Data Source

Step Five

The ComboBox will provide Customer selection. To wire up the ComboBox drag the Customer object and drop it on the ComboBox as pictured in Figure 17.

Figure 17 Binding ComboBox

  • Select the ComboBox
  • Using the Properties Window set the DisplayMemberPath to Name
  • Run application. You should be able to view data as pictured in Figure 18.

Figure 18 Run Application

Note

As part of the Solution Starter, the ApplicationMainWindow Loaded event has code that populates the CollectionViewSource for the application. This is code that developers would normally have to write as the Object Source drag and drop from the Data Sources Window does not add code to your projects.



Adding the Details Form

The details form in this application plays the role of the Master in our Master-Details application.

Step One

Customize the Customer object output.

Figure 19 Change Layout Type

  • Change the Customer object layout to Details as pictured in Figure 19 above

 

Figure 20 Change CustomerID Control

  • Change the CustomerID field to use the Label control when rendered as pictured in Figure 20 above

Step Two

Figure 21 Adding New Row

  • Select the Grid and add a new row as pictured in Figure 21 above.

Figure 22 Details Form Generation

  • Drag and drop the Customer object to the Grid Row below the ComboBox
  • With the Details Grid selected, use the Properties Window and reset the following properties:
    • Height
    • Width
  • Using the Properties Window set the following properties:
    • VerticalAlignment to Top
    • Margin to 11
  • Select the outer Grid and change the Details Form row to use Auto sizing
  • The application should now look like Figure 23 below
  • Run the application and select different Customers

Figure 23 Details Form Completed

Adding the DataGrid

Step One

Customize the Addresses object output.

  • Expand the Address node
  • Set the CustomerID field control to None

Step Two

Figure 24 Add Grid to Bottom Row

  • Add a Grid control to the bottom row
  • With Grid selected, right click, select Reset Layout, All
  • Using the Properties Window set the following property:
    • Margin to 11

Step Three

Figure 25 Drag and Drop DataGrid

  • Drag and drop the Addresses object from the Data Sources Window to the Grid control added in Step Two above
  • With DataGrid selected, right click, select Reset Layout, All
  • The DataGrid should now look like Figure 26 below

 

 

DataGridResized

Figure 26 Data Grid Resized

Step Four

Edit DataGrid columns using the XAML Editor.

Figure 27 DataGrid Columns

  • Insert a DataGridComboBoxColumn as pictured in Figure 27 above by copying the below XAML:

<DataGridComboBoxColumn SelectedValueBinding="{Binding Path=AddressType.AddressTypeId, Mode=TwoWay}" ItemsSource="{x:Static local:Data.AddressTypes}" DisplayMemberPath="Name" Header="Address Type" SelectedValuePath="AddressTypeId" />

  • Cut and Paste the Street column so that it is above the City column as pictured in Figure 27 above.
  • Run you application
    • You can add, edit and delete rows in the DataGrid
    • Notice that the ComboBox in the DataGrid provides selection for the Address, AddressType.
Note

See How does it Work section below for an explanation of the DataGrid ComboBox.



How does it Work?

The CollectionViewSource is a powerful class that provides a wrapper around a data source, adding sorting, grouping and filtering functionality without changing the source data.

The CollectionViewSource is a proxy class to the underlying CollectionView that provides navigation of collection items.

Information

MSDN CollectionViewSource documentation can be viewed here: http://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.aspx

Figure 28 Data Object Relationships

  • The Data.Customers ObservableCollection is the source for the CustomerViewSource. This data is wired up in the ApplicationMainWindow.Loaded event.
  • When the ComboBox selection changes it sets the CurrentItem on the underlying CollectionView.
  • The Details Form is bound to the CurrentItem. When selection changes, the Details Form DataContext changes and the selected Customer is displayed.
  • The CustomerAddressesViewSource is bound to the CurrentItem (current Customer) Addresses property.
  • The DataGrid is bound to the CustomerAddressesViewSource and displays all items in this collection.

DataGrid ComboBox

The DataGrid ComboBox displays the AddressType.Name for the Address and provides selection of an AddressType.

Figure 29 DataGrid ComboBox

  • SelectedValueBinding property gets and sets the AddressTypeId for the Address in the row
  • ItemsSource is set to the static (Shared) property AddressTypes exposed by the Data class. AddressTypes is a collection of AddressType.
  • DisplayMemberPath is the Name property of the AddressType
  • Header is the column header displayed in the DataGrid
  • SelectedValuePath is the AddressTypeId of the AddressType
Information

MSDN DataGridComboBoxColumn documentation can be viewed here:http://msdn.microsoft.com/en-us/library/system.windows.controls.datagridcomboboxcolumn(VS.100).aspx



Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above feature enables your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Create First Silverlight Application

This article has a corresponding video that can be viewed here.

Are you new to Silverlight? This walkthough will enable you to have a successful first time experience with the Silverlight Designer and creating your first Silverlight application. You will learn to easily create, move and align controls and edit control collections using the powerful features of the Silverlight Designer for Visual Studio 2010. We will complete the exercise by developing a Survey Silverlight application.

Requirements

View the Setting up Visual Studio for WPF and Silverlight Development topic.

New Project

The first three short sections of this walk though introduce you to using the Silverlight Designer for creating, moving, aligning and sizing controls.

Silverlight applications are all hosted on a web page. The Silverlight application can consume the entire web page, or be integrated into a web page and interact with other web controls. This application will be a small survey application that simply displays in the upper left corner of the web page.

To create your first Silverlight Application Project

  1. Start Visual Studio 2010.
  2. From the File menu hover over New, then select New Project…

     FileNewProject

    Figure 1 New Project Menu Selection

  3. New Project Dialog will be displayed.

     NewProjectDialogOriginal

    Figure 2 New Project Dialog

Note

The Target Framework Version ComboBox value defaults to the last selection made. When creating a new project, verify the desired Target Framework Version is selected.

In Silverlight applications, the Target Framework Version refers to the ASP.NET Web Site that will be hosting the Silverlight application and not the Silverlight application itself.

  • Step 1 – Select language; Visual Basic or C# then select Silverlight.
  • Step 2 – Select Silverlight Application.
  • Step 3 – Enter project name.
Tip

While it is permissible to have spaces in the project name this practice discouraged.

  • Step 4 – Click OK. The Add Silverlight Application dialog will display.
  1. Add Silverlight Application dialog allows the developer to choose how the Silverlight Application will be hosted during development.

     AddSilverlightApplication

    Figure 3 Add Silverlight Application

    1. Step 1 – Select, "Automatically generate a test page to host Silverlight at build time." This is the simplest way to develop a Silverlight application as it does not require an ASP.NET web site to be created. When the Silverlight application is run, Visual Studio will create web page on the fly to host the Silverlight application and open that web page in the default browser.
    2. Step 2 – Select the version of Silverlight you are targeting.
    3. Step 3 – Click OK to create your new Silverlight Application.

Creating Controls

Controls can be added to an application using the ToolBox or by editing the XAML text directly in the XAML Editor.

  1. Several techniques can be used to add a control from the ToolBox.
    1. Select a control from the ToolBox by clicking it, then clicking the design surface where you want the control to be created.
    2. Select a control from the ToolBox by clicking it, and then draw the control on the design surface where you want the control to be created.
    3. Click and drag a control from the ToolBox to the design surface. See Figure 4 below.
    4. With the target control selected on the design surface, double click the control in the ToolBox.

     CreateControl

    Figure 4 Create Control

    1. Practice creating a button control using the above techniques on the design surface. When done create a button in the position shown in Figure 4.
    2. Notice when you drag the button to the design surface, the Grid control's blue adorner is displayed.

Control Adorners and Snaplines

The Silverlight Designer displays control adorners on the design surface to assist developer when using the mouse to move or resize a control. Adorners also supply visual feedback about control alignment and other control specific information.

When controls are being moved or resized, the Silverlight Designer displays various types of snaplines to assist the developer in positioning a control on the design surface relative to other controls.

  1. Alignment Adorners
    1. Select the button on the design surface.
    2. In the Properties Window, select Category View and scroll the Layout category into view as in Figure 5 below.
    3. The button in Figure 5 is aligned to the Top, Left. This is similar to Windows Forms Docking.
      1. The button's top edge is pinned 37 pixels down from the top of the Grid. (see second value in the Margin property below)
      2. The button's left edge is pinned 31 pixels from the Grid. (see first value in the Margin property below)

     ControlAlignmentAdorners

    Figure 5 Alignment Adorners

Tip

The Margin property is of type Thickness. The property values are read left, top, right and bottom. A Thickness can also be represented with a single value or with two values. If a single value is supplied, all four sides are equal. If two values are supplied they are read (left and right), (top and bottom).

  1. Change the HorizontalAlignment property value using the Properties Window and notice the different adorners that are rendered. The green arrow in Figure 6 below indicates the HorizontalAlignment adorner.
    1. You can also change the HorizontalAlignment property by clicking on the adorner arrow or the round adorner pointed to by the green arrow.
  2. Repeat for the VerticalAlignment property. The blue arrow in Figure 6 below indicates the VerticalAlignment adorner.
  3. Return the button back to Top, Left alignment.
  4. The red arrow in Figure 6 points to the resize adorner. Clicking and dragging a resize adorner will resize the control in the direction of the mouse movement.

 ControlAdorners

Figure 6 Alignment and Resize Adorners

  1. Edge Snaplines
    1. To move a control on the design surface, select it, hold the left mouse down and move the control using the mouse. Release left mouse button when move is complete.
    2. When moving a control near the edge of a container control like a grid an edge snapline will appear. This snapline makes it very easy to uniformly position one or more controls against the containers edge.
    3. In Figure 7 below, notice the two numbers in the left red rectangle. 12 and 12 indicate that the top left corner of the button is 12 pixels from the top and 12 pixels from the left of the grid.
    4. The right red rectangle in Figure 7 contains 213. This indicates the number of pixels from the right edge of the button to the edge of the grid.
    5. When moving a control, if you move the control past the edge snapline, the control will snap to the edge of the container control.

    Figure 7 Edge Snaplines

Tip

To turn off Snaplines when moving a control, hold the ALT key down while dragging the control around on the design surface.

Use arrow keys to nudge a control, pixel by pixel into perfect position!

  1. Control Snaplines
    1. Add another button to the form as picture below.
    2. Figure 8 shows the control snaplines that are displayed when the edges of one control line up with another. The number 20 is the number of pixels that separate the two buttons.

    Figure 8 Control Snaplines

Survey Application – Form Title

At this time delete any buttons or other controls you have placed on the design surface. Select the control and press the DELETE key to delete the control.

Please save your application by pressing CTRL+S or by clicking the Save icon on the ToolBar.

First Silverlight Application

The rest of this walk through will focus on creating this Simple Survey application. You will learn many new features of the Silverlight Designer while building this application.

Figure 9 Finished Application

  1. Fixed Sized Layout
    1. By default the root UserControl is auto sized at runtime. At design time the root UserControl is explicitly sized to make it easy to design.

     AutoSizedRoot

    Figure 10 Default Auto Sized Root

    1. For this survey application we want a fixed size root so that our application will not consume the entire Internet browser window. To change from auto sized root to fixed size root, click the Size Mode button inside the red rectangle. See Figure 11 below. After you click the Size Mode button the button icon changes to reflect the current root size mode. Additionally a fixed Height and Width are now set on the root UserControl.

     FixedLayoutRoot

    Figure 11 Fixed Size Root

    1. Setting the root UserControl layout size.
      1. Select the root UserControl by clicking anywhere on the designer outside the UserControl's border.
      2. Change the Properties Window to Category View and scroll the Properties Window until Layout is visible as pictured in Figure 12 below.
      3. Change the Height and Width as indicated in Figure 12.

       RootHeightWidth

      Figure 12 Root Height and Width

  2. Create a TextBlock control to the design surface.
    1. The TextBlock control is located in the Silverlight Controls tab of the ToolBox.
  3. With the new TextBlock selected, set the Properties Window to Alpha View and enter, "text" in the Search Box. Notice as you type, the list of properties is quickly filtered.
Tip

The search feature of the Properties Window filters the properties and can save you lots of time during application development. Very handy.

  1. Change the Text property to Survey.

     TextBlockText

    Figure 13 Form Title - TextBlock Text

  2. We will now use the Properties Window to position the Title TextBlock.
    1. Change the Properties Window to Category View and scroll to the Layout category as shown in Figure 14 below.
    2. Set the HorizontalAlignment, VerticalAlignment and Margin properties as indicated below. Notice how the TextBlock is positioned on the design surface.
  3. Using the Search Box, enter font. Use the Font Category editor and increase the Font Size to 18.

     TextBlockPositioning

    Figure 14 Form Title - TextBlock positioning

Note

In Figures 13 and 14, notice the preview of the TextBlock in the Preview Icon displayed to the left of the control name. This same Preview Icon is also displayed in the Document Outline when the mouse is hovered over controls listed there.

Survey Application – Form Controls Part I

It's time to give our user interface (UI) some controls the user can interact with at run-time.

  1. Add the four controls pictured in Figure 15, two TextBlocks, TextBox and a ComboBox.
    1. Align all controls Top, Left.
    2. Use the control snaplines to assist in aligning and positioning the controls
    3. Select the TextBox. Using the Properties Window change the Name to txtName.
    4. Select the ComboBox. Change the Name to cboProduct.

    Figure 15 Form Controls

  2. Select the top TextBlock on the design surface.
    1. Use Properties Window search feature and type in, "tex".
    2. Change the Text property to, "Name".
  3. Click the bottom TextBlock on the design surface.
    1. Notice that the Text property for that TextBlock is now selected in the Properties Window.
    2. Change the Text property to, "Product".

    Figure 16 TextBlock Text Property

  4. There are several ways to add items to a ComboBox. In this walk through we will add three static items to the ComboBox.
    1. Select the ComboBox.
    2. Search for items in the Properties Window. See Figure 17 below.
    3. Click the Items property ellipsis icon to open the Collection Editor for the Items property.

    Figure 17 ComboBox Items Collection

  5. Adding items is very easy using the Collection Editor.
    1. Click on the Add button.
    2. Locate the Content property and change the value.
    3. You can also order the items or remove an item.
  6. Using the Collection Editor in Figure 18, add three items, setting the Content property to the following strings:
    1. Deluxe Photo Paper
    2. Financial Calculator
    3. 4GB USB Thumb Drive
  7. Click OK when done.
    1. In the XAML Editor, look at the XAML markup that was generated for you.

    Figure 18 Collection Editor

Survey Application – Form Controls Part II

In this section we will use a Border to surround the RadioButtons. RadioButtons are mutually exclusive; meaning that when one is selected the previously selected RadioButton is deselected automatically.

We will also introduce a new panel control, the StackPanel. StackPanels stack their child controls either horizontally or vertically based on their Orientation property.

  1. Below the ComboBox add a Border control from the ToolBox Controls tab.

 NewBorderWithoutChild

Figure 19 Border

  1. The Border control can contain a single child control.
  2. To add a StackPanel as a child of the Border drag the StackPanel control from the ToolBox to the Border. See Figure 20 below. Notice the blue adorner surrounding the Border. This indicates the parent control that your StackPanel will be a child of if dropped at the current location.

    Figure 20 Parenting Control on Creation

  3. When controls are added to the design surface using the ToolBox some properties are given default values.
Tip

You can also drag controls from the ToolBox to the XAML Editor. When a control is dragged to the XAML editor, no properties are given default values.

  1. After creating the StackPanel the design surface will look similar to Figure 21 below. Notice in the XAML Editor and Document Outline that the StackPanel is a child of the Border.

 StackPanelDroppedIntoBorder

Figure 21 StackPanel as a child of the Border 

  1. For our application we want the StackPanel to automatically consume all the space inside the Border so that if the Border is resized at design or run-time, the StackPanel will grow or shrink with the Border.
  2. Let's use the Properties Window to accomplish this task. See Figure 22 below.
    1. With the StackPanel selected, search for "wid" in the Properties Window.
    2. Click the Property Marker for the Width property and select Reset Value. This will change the Width property to Auto.

    Figure 22 Resetting Property Values

    1. Repeat for the Height property, setting its value to Auto.
    2. Search for "align". Reset the property value for the HorizontalAlignment and VerticalAlignment properties. When reset, their value will be changed to Stretch. The StackPanel is now auto sized and should look like Figure 23.

    Figure 23 Auto Sized StackPanel

  3. With the StackPanel selected, add a TextBlock and three RadioButtons as children of the StackPanel by double clicking the TextBlock once and double clicking the RadioButton in the ToolBox three times. When completed the design surface will look similar to Figure 24 below.
  4. A powerful feature of the Silverlight Designer is the ability to select multiple controls and edit common property values.
  5. Select all four controls by control clicking them. (CTRL+Click). Notice that the Properties Window Name changes to Multiple objects selected.
    1. Use the Properties Window to reset the Height and Width property values for the selected controls.
    2. Using the Properties Window, search for "margin" and set the value to 3.5. Depending on the size of your Border the setting of the Margin property may cause one or more RadioButtons to disappear from view, we will correct that next.
  6. Select the TextBlock by clicking on it. Change its Margin property to 0,3.5. This will cause the TextBlock to render slightly left of the RadioButtons.

    Figure 24 Multi-Selection Control Editing 

Tip

You can also multi-select all controls in a container by selecting the container and pressing CTRL+A. In figure 24 above, select the StackPanel and press CTRL+A to select the three RadioButtons.

 

  1. On the design surface select the Border, use the resize adorner on the bottom and resize the Border so it looks like Figure 25 below.
    1. Notice how the child StackPanel automatically resizes when its parent Border is resized.

    Figure 25 Resizing GroupBox

  2. Use the Properties Window to assign the TextBlock Text property to Value. See Figure 26 below.

    Figure 26 Border Caption

  3. Use the Properties Window to assign the following values to the three RadioButtons Content properties.
    1. Outstanding
    2. Good
    3. Unsatisfied

    Figure 27 RadioButton Content

  4. Select the Border. Use the Properties Window to set the follow properties:
    1. CornerRadius to 5
    2. BorderBrush to LightGray
    3. BorderThickness to 1
    4. Padding to 3.5
  5. The Border and contents should now look like Figure 28.

    Figure 28 Completed Border

  6. You can set a default value for the ComboBox by assigning a value to the SelectedIndex property.
  7. Select the ComboBox, use the Properties Window change the SelectedIndex property to 0.
    1. Notice how the ComboBox now displays the value of the ComboBoxItem at index 0. See Figure 29 below.

     ComboBoxSelectedItem

    Figure 29 ComboBox Selected Index

Survey Application – Form Controls Part III

To complete our application we need to add two Buttons and add some code that will execute when the Button is clicked.

  1. Add two buttons as pictured in Figure 30 below.
    1. Change the left Button Content property to OK and set the Name property to btnOK.
    2. Change the right Button Content property to Cancel and set the Name property to btnCancel.
  2. The Silverlight Designer provides three ways to wire up code to a control event.
    1. Double clicking a control will wire up the default event.
    2. Using the Properties Window Events tab, locate the desired event and double click the region indicated in Figure 30.
      1. If the event code is already in the code behind, you can select the method name in the ComboBox instead of double clicking to create a new event handler.
    3. Using the XAML Editor to create a new event handler or select a method.
  3. Select the OK Button. Using the Properties Window Events tab, double click next to the Click event. This will wire up the Click event handler and add code the code behind.

    Figure 30 Properties Window Events Tab 

    1. Visual Basic wires up the event using the Handles construct.
    2. C# wires up the event by adding the event name and event handler to the XAML markup.
  4. On the design surface, double click the Cancel Button to generate the event handler for this Button.
    1. Add the MessageBox.Show method call to the generated event handlers.

Visual Basic Code

Partial Public Class Page
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub btnOK_Click(ByVal sender As System.Object,
                            ByVal e As System.Windows.RoutedEventArgs) Handles btnOK.Click
        MessageBox.Show("Thank you for your feedback")
    End Sub

    Private Sub btnCancel_Click(ByVal sender As System.Object,
                                ByVal e As System.Windows.RoutedEventArgs) Handles btnCancel.Click
        MessageBox.Show("Survey cancelled")
    End Sub
End Class

C# Code

namespace FirstSilverlightApplication
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Thank you for your feedback");
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Survey cancelled");
        }
    }
}
  1. Use the Document Outline to select root Grid. See Figure 31 below.

    Figure 31 Document Outline Selecting Root Grid 

  2. Using the Brush Editor in the Properties Window, change the Background color to WhiteSmoke as picture in Figure 32.
    1. The reason we are changing the Background color is so that you can see the boundaries of the Silverlight application when its run while being hosted in a white web page.

     RootGridBackground

    Figure 32 Root Grid Background

  3. Run your completed application by pressing F5.
    1. Enter a name in the name TextBox.
    2. Select a product from the ComboBox.
    3. Click the RadioButtons to see how only one is selected at time.
    4. Clicking the OK or Cancel buttons will cause the MessageBox to display its message.

    Figure 33 Running the Application

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above feature enables your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

Create First WPF Application

This article has a corresponding video that can be viewed here.

Are you new to WPF? This walk though will enable you to have a successful first time experience with the WPF Designer and creating your first WPF application. You will learn to easily create, move and align controls, create data bindings and edit control collections using the powerful features of the WPF Designer for Visual Studio 2010. We will complete the exercise by developing a Survey form.

Requirements

View the Setting up Visual Studio for WPF and Silverlight Development topic.

New Project

The first four short sections of this walk though introduce you to using the WPF Designer for creating, moving, aligning and sizing controls.

To create your first WPF Application Project

  1. Start Visual Studio 2010.
  2. From the File menu hover over New, then select New Project…

    FileNewProject

    Figure 1 New Project Menu Selection

  3. New Project Dialog will be displayed.

    NewProjectDialogOriginal

    Figure 2 New Project Dialog

Note

The Target Framework Version ComboBox value defaults to the last selection made. When creating a new project, verify the desired Target Framework Version is selected.

  • Step 1 – Select language; Visual Basic or C# then select Windows.
  • Step 2 – Select WPF Application.
  • Step 3 – Enter project name.
Tip

While it is permissible to have spaces in the project name this practice discouraged.

  • Step 4 – Click OK to create your new WPF Application.

Editing Window Title

Let's give our application a proper title. The Title property is displayed in the top left side of the window chrome.

  1. Select the Window object by clicking on the Window border in the designer or by clicking the design surface outside of the window contents.
    1. Notice the Window object four corners now have resize adorners. These are used when resizing the Window object with the mouse.
    2. Notice the Window object's properties are now displayed in the Properties Window and that the Title property is selected.
Note

Each control has a default property that is automatically selected in the Properties Window when that control is selected.

  1. Change the Title property to "First WPF Application"

    FirstWPFApplicationPropertyBrowser

    Figure 3 Properties Window  

    1. The designer keeps all related tool windows and view synchronized for your selection.

    FirstWPFApplicationDesignerXAMLEditor

    Figure 4 WPF Designer and XAML Editor

Creating Controls

Controls can be added to an application using the ToolBox or by editing the XAML text directly in the XAML Editor.

  1. Several techniques can be used to add a control from the ToolBox.
    1. Select a control from the ToolBox by clicking it, then clicking the design surface where you want the control to be created.
    2. Select a control from the ToolBox by clicking it, and then draw the control on the design surface where you want the control to be created.
    3. Click and drag a control from the ToolBox to the design surface. See Figure 5 below.
    4. With the target control selected on the design surface, double click the control in the ToolBox.

    CreateControl

    Figure 5 Create Control

    1. Practice creating a button control using the above techniques on the design surface. When done create a button in the position shown in Figure 5.
    2. Notice when you drag the button to the design surface, the Grid control's blue rail adorner is displayed.

Control Adorners and Snaplines

The WPF Designer displays control adorners on the design surface to assist developer when using the mouse to move or resize a control. Adorners also supply visual feedback about control alignment and other control specific information.

When controls are being moved or resized, the WPF Designer displays various types of snaplines to assist the developer in positioning a control on the design surface relative to other controls.

  1. Alignment Adorners
    1. Select the button on the design surface.
    2. In the Properties Window, select Category View and scroll the Layout category into view as in Figure 6 below.
    3. The button in Figure 6 is aligned to the Top, Left. This is similar to Windows Forms Docking.
      1. The button's top edge is pinned 37 pixels down from the top of the Grid. (see second value in the Margin property below)
      2. The button's left edge is pinned 38 pixels from the Grid. (see first value in the Margin property below)

    ControlAlignmentAdorners

    Figure 6 Alignment Adorners

Tip

The Margin property is of type Thickness. The property values are read left, top, right and bottom. A Thickness can also be represented with a single value or with two values. If a single value is supplied, all four sides are equal. If two values are supplied they are read (left and right), (top and bottom).

  1. Run your application by pressing F5.
    1. After the application starts, resize the window. Notice the button does not move as the window is resized.
  2. Take a minute and change the HorizontalAlignment property values using the Properties Window and notice the different adorners that are rendered. The green arrow in Figure 7 below indicates the HorizontalAlignment adorner.
    1. After changing the HorizontalAlignment property, re-run the application and resize the window. Notice when the button moves or is resized based on how it is aligned as the window is resized.
    2. You can also change the HorizontalAlignment property by clicking on the adorner arrow or the round adorner pointed to by the green arrow.
  3. Repeat for the VerticalAlignment property. The blue arrow in Figure 7 below indicates the VerticalAlignment adorner.
  4. Return the button back to Top, Left alignment.
  5. The red arrow in Figure 7 points to the resize adorner. Clicking and dragging a resize adorner will resize the control in the direction of the mouse movement.

ControlAdorners

Figure 7 Alignment and Resize Adorners

  1. Edge Snaplines
    1. To move a control on the design surface, select it, hold the left mouse down and move the control using the mouse. Release left mouse button when move is complete.
    2. When moving a control near the edge of a container control like a grid an edge snapline will appear. This snapline makes it very easy to uniformly position one or more controls against the containers edge.
    3. In Figure 8 below, notice the two numbers in the left red rectangle. 12 and 12 indicate that the top left corner of the button is 12 pixels from the top and 12 pixels from the left of the grid.
    4. The right red rectangle in Figure 8 contains 191. This indicates the number of pixels from the right edge of the button to the edge of the grid.
    5. When moving a control, if you move the control past the edge snapline, the control will snap to the edge of the container control.

    EdgeSnapLines

    Figure 8 Edge Snaplines (EdgeSnapLines.png)

Tip

To turn off Snaplines when moving a control, hold the ALT key down while dragging the control around on the design surface.

Use arrow keys to nudge a control, pixel by pixel into perfect position!

  1. Control Snaplines
    1. Add another button to the form as picture below.
    2. Figure 9 shows the control snaplines that are displayed when the edges of one control line up with another. The number 20 is the number of pixels that separate the two buttons.

    ControlSnaplines

    Figure 9 Control Snaplines

  2. Text Baseline Snaplines
    1. Figure 10 shows the text baseline snapline that is displayed when two text controls are aligned. The number 20 is the number of pixels that separate the two buttons.

    TextBaseLines

    Figure 10 Text Baseline Snaplines

Survey Application – Form Title

At this time delete any buttons or other controls you have placed on the design surface by selecting the control and pressing the DELETE key to delete the control.

Please save your application by pressing CTRL+S or by clicking the Save icon on the ToolBar.

First WPF Application

The rest of this walk through will focus on creating this Simple Survey application. You will learn many new features of the WPF Designer while building this application.

CompletedApplication

Figure 11 Completed Application

  1. Create a TextBlock control to the design surface.
    1. The TextBlock control is located in the Controls tab of the ToolBox.
  2. With the new TextBlock selected, set the Properties Window to Alpha View and enter, "text" in the Search Box. Notice as you type, the list of properties is quickly filtered.
Tip

The search feature of the Properties Window filters the properties and can save you lots of time during application development. Very handy.

  1. Change the Text property to Survey.

    TextBlockText

    Figure 12 Form Title - TextBlock Text 

  2. We will now use the Properties Window to position the Form Title TextBlock.
    1. Change the Properties Window to Category View and scroll to the Layout category as shown in Figure 13 below.
    2. Set the HorizontalAlignment, VerticalAlignment and Margin properties as indicated below. Notice how the TextBlock is positioned on the design surface.
  3. Using the Search Box, enter font. Use the Font Category editor and increase the Font Size to 18.

    TextBlockAlignment

    Figure 13 Form Title - TextBlock positioning

Note

In Figures 12 and 13, notice the preview of the TextBlock in the Preview Icon displayed to the left of the control name. This same Preview Icon is also displayed in the Document Outline when the mouse is hovered over controls listed there.

Survey Application – Form Controls Part I

It's time to give our user interface (UI) some controls the user can interact with at run-time.

  1. Add the four controls pictured in Figure 14, two Labels, TextBox and a ComboBox.
    1. Align all controls Top, Left.
    2. Use the control snaplines to assist in aligning and positioning the controls
    3. Select the TextBox. Using the Properties Window change the Name to txtName.
    4. Select the ComboBox. Change the Name to cboProduct.

    TopFormControls

    Figure 14 Form Controls

  2. Select the top label on the design surface.
    1. Use Properties Window search feature and type in, "con".
    2. Change the Content property to, "_Name".
  3. Click the bottom label on the design surface.
    1. Notice that the Content property for that label is now selected in the Properties Window.
    2. Change the Content property to, "_Product".

    LabelContent

    Figure 15 Label Content Property

Note

The Label control uses the Content property to display its text. You may be thinking why is the text for the Label in the Content property and the text for the TextBlock in the Text property? This is because the two properties are different data types with different associated features.

The Label Content property can contain just about anything, text, image, grid, etc.

The Label control can associate an Access Key with another control, so that when the Access Key is pressed, focus will be moved to the target control. The Label Content property plays a role in this.

The TextBlock Text property is special. It can contain text or inline content flow elements. See http://msdn.microsoft.com/en-us/library/bb613554.aspx for more information on inline content. Inline content allows you to have multi-line formatted content in a TextBlock.

  1. Implementing a label Access Key requires an Access Key and Target control assignment.
    1. "_N" associates the key combination ALT+N with this label's Access Key. When the user holds down the ALT key the label will be displayed as "Name".
    2. In WPF the Target control is assigned using data binding.
    3. The Properties Window Data Binding Builder provides the UI for creating the required data binding.
  2. Setting the Target Property for the Access Key.
    1. In the following steps we'll create what is called an "element name binding." Element name bindings enabled a control to bind to property on another named object.
    2. Select the TextBox control and enter "tar" in the Properties Window Search Box. See Figure 16 below.
    3. The red arrow is pointing to the Property Marker. The Property Marker icon changes based on property value assignment and where the property is being assigned.
    4. Click the Property Marker and the context menu is displayed.
    5. Selected Apply Data Binding…

    SearchTargetClickPropertyMarker

    Figure 16 Binding Target Property

    1. In the Source tab, select ElementName. A list of named UI controls will be displayed.
    2. Select txtName. Notice the Source tab title is updated as you perform the selections.
      1. The Target binding does not require that a Path be assigned.
      2. To close the Data Binding Building press ENTER or click outside the Data Binding Builder.

    TargetBindingToTextBox

    Figure 17 Data Binding Builder

    1. Let's test our ALT+N Access Key. Run your application and press ALT+N. Focus is moved to the TextBox control.
  3. Repeat the above steps for the Product label, associating ALT+P with the ComboBox as the Target.
Important

You have just data bound labels to their associated TextBox to enable Access Key control selection. Data binding in WPF is one of the most powerful features of the platform and is used extensively in all WPF applications. For example, binding UI controls to database or collection data, or intra-form binding that provides an interactive experience for users of your application. You will find that data binding in the UI will save you from writing a lot of code you would normally write if developing on another platform.

A proper understand of WPF Data Binding is essential for the WPF developer. MSDN documentation provides clear and concise information that you can read here http://msdn.microsoft.com/en-us/library/ms752347.aspx.

  1. There are several ways to add items to a ComboBox. In this walk through we will add three static items to the ComboBox.
    1. Select the ComboBox.
    2. Search for items in the Properties Window. See Figure 18 below.
    3. Click the Items property ellipsis icon to open the Collection Editor for the Items property.

    ComboBoxItemsCollection

    Figure 18 ComboBox Items Collection

  2. Adding items is very easy using the Collection Editor.
    1. Click on the Add button.
    2. Locate the Content property and change the value.
    3. You can also order the items or remove an item.
  3. Using the Collection Editor in Figure 19, add three items, setting the Content property to the following strings:
    1. Deluxe Photo Paper
    2. Financial Calculator
    3. 4GB USB Thumb Drive
  4. Click OK when done.
    1. In the XAML Editor, look at the XAML markup that was generated for you.

    CollectionEditor

    Figure 19 Collection Editor

Survey Application – Form Controls Part II

In this section we will use a GroupBox to display RadioButtons. RadioButtons are mutually exclusive; meaning that when one is selected the previously selected RadioButton is deselected automatically.

We will also introduce a new panel control, the StackPanel. StackPanels stack their child controls either horizontally or vertically based on their Orientation property.

  1. Below the ComboBox add a GroupBox control from the ToolBox Controls tab.
  2. The GroupBox control can contain a single child control. The WPF Designer automatically adds a child Grid control for you. See Figure 20 below.
  3. We want to replace the Grid with a StackPanel. You can either edit the XAML markup directly by changing <Grid /> to <StackPanel /> or you can use the designer.
  4. Select the GroupBox Grid by clicking inside the GroupBox.
    1. Press the DELETE key to delete the child Grid.

    GroupBoxGridSelected

    Figure 20 GroupBox

  5. To add a StackPanel as a child of the GroupBox drag the StackPanel control from the ToolBox to the GroupBox. See Figure 21 below. Notice the blue adorner surrounding the Border. This indicates the parent control that your StackPanel will be a child of if dropped at the current location.

    DragStackPanelInSideGroupBox

    Figure 21 Parenting Control on Creation

  6. When controls are added to the design surface using the ToolBox some properties are given default values.
Tip

You can also drag controls from the ToolBox to the XAML Editor. When a control is dragged to the XAML editor, no properties are given default values.

  1. After creating the StackPanel the design surface will look similar to Figure 22 below. Notice in the XAML Editor and Document Outline that the StackPanel is a child of the GroupBox.

StackPanelDroppedIntoGroupBox

Figure 22 StackPanel as a child of the GroupBox

  1. For our application we want the StackPanel to automatically consume all the space inside the GroupBox so that if the GroupBox is resized at design or run-time, the StackPanel will grow or shrink with the GroupBox.
  2. Let's use the Properties Window to accomplish this task. See Figure 23 below.
    1. With the StackPanel selected, search for "wid" in the Properties Window.
    2. Click the Property Marker for the Width property and select Reset Value. This will change the Width property to Auto.

    ResettingWidth

    Figure 23 Resetting Property Values

    1. Repeat for the Height property, setting its value to Auto.
    2. Search for "align". Reset the property value for the HorizontalAlignment and VerticalAlignment properties. When reset, their value will be changed to Stretch. The StackPanel is now auto sized and should look like Figure 24.

    StackPanelFillingGroupBox

    Figure 24 Auto Sized StackPanel

  3. Let's give the GroupBox a meaningful heading. Using the Properties Window search for "head" and change the Header property to "Value". See Figure 25 below.
  4. With the StackPanel selected, add three RadioButtons as children of the StackPanel by double clicking the RadioButton in the ToolBox three times. When completed the design surface will look similar to Figure 25 below.
  5. A powerful feature of the WPF Designer is the ability to select multiple controls and edit common property values.
  6. Select the three RadioButtons by control clicking them. (CTRL+Click). Notice that the Properties Window name changes to, "Multiple objects selected."
    1. Use the Properties Window to reset the Height and Width property values for the selected RadioButtons.
    2. Using the Properties Window, search for "margin" and set the value to 3.5. Depending on the size of your GroupBox the setting of the Margin property may cause one or more RadioButtons to disappear from view, we will correct that next.

    ConfigureRadioButtons

    Figure 25 Multi-Selection Control Editing

Tip

You can also multi-select all controls in a container by selecting the container and pressing CTRL+A. In figure 25 above, select the StackPanel and press CTRL+A to select the three RadioButtons.

  1. On the design surface select the GroupBox, use the resize adorner on the bottom and resize the GroupBox so it looks like Figure 26 below.
    1. Notice how the child StackPanel automatically resizes when its parent GroupBox is resized.

    ResizingGroupBox

    Figure 26 Resizing GroupBox

  2. Use the Properties Window to assign the following values to the three RadioButtons Content properties.
    1. Outstanding
    2. Good
    3. Unsatisfied

    RadioButtonContent

    Figure 27 RadioButton Content

  3. You can set a default value for the ComboBox by assigning a value to the SelectedIndex property.
  4. Select the ComboBox, use the Properties Window change the SelectedIndex property to 0.
    1. Notice how the ComboBox now displays the value of the ComboBoxItem at index 0. See Figure 28 below.

    ComboBoxSelectedIndex

    Figure 28 ComboBox Selected Index

Survey Application – Form Controls Part III

To complete our application we need to add two Buttons and add some code that will execute when the Button is clicked.

  1. Add two buttons as pictured in Figure 29 below.
    1. Change the left Button Content property to OK and set the Name property to btnOK.
    2. Change the right Button Content property to Cancel and set the Name property to btnCancel.
  2. The WPF Designer provides three ways to wire up code to a control event.
    1. Double clicking a control will wire up the default event.
    2. Using the Properties Window Events tab, locate the desired event and double click the region indicated in Figure 29.
      1. If the event code is already in the code behind, you can select the method name in the ComboBox instead of double clicking to create a new event handler.
    3. Using the XAML Editor to create a new event handler or select a method.
  3. Select the OK Button. Using the Properties Window Events tab, double click next to the Click event. This will wire up the Click event handler and add code the code behind.

    PropertyGridEventsTabCreateClickEvent

    Figure 29 Properties Window Events Tab

    1. Visual Basic wires up the event using the Handles construct.
    2. C# wires up the event by adding the event name and event handler to the XAML markup.
  4. On the design surface, double click the Cancel Button to generate the event handler for this Button.
    1. Add the MessageBox.Show and Close method calls to the generated event handlers.

Visual Basic Code

Class FirstWPFApplication

    Private Sub btnCancel_Click(ByVal sender As System.Object,
                                ByVal e As System.Windows.RoutedEventArgs
                                ) Handles btnCancel.Click

        Me.Close()
    End Sub

    Private Sub btnOK_Click(ByVal sender As System.Object,
                            ByVal e As System.Windows.RoutedEventArgs
                            ) Handles btnOK.Click

        MessageBox.Show("Thank you for your feedback")
        Me.Close()
    End Sub

End Class

C# Code

namespace FirstWPFApplication
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window { 
        public Window1() {
            InitializeComponent();
        }

        private void btnOK_Click(object sender, RoutedEventArgs e) {
            MessageBox.Show("Thank you for your feedback.");
            this.Close();
    }

        private void btnCancel_Click(object sender, RoutedEventArgs e) {
            this.Close();

        }
    }
}
  1. Run your completed application by pressing F5.
    1. Use the Access Key ALT+N to set focus to the TextBox.
    2. Now use ALT+P to set focus to the ComboBox.
      1. Use arrow keys to change the ComboBox value.
      2. Press F4 to open the ComboBox dropdown.
    3. Click the RadioButtons to see how only one is selected at time.
    4. Clicking Cancel will close the application.
    5. Clicking OK will cause the MessageBox to display its message. Close the MessageBox and the application will close.

    TestApplication

    Figure 30 Running the Application

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above feature enables your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

How to Insert a Row in a Data Entry Form

This article has a corresponding video that can be viewed here.

A common task after a form is developed is inserting a new row in the form. This short walk-through will show you how to insert a new row in an existing data entry form.

For this exercise our requirement is to insert a Label and TextBox for the middle initial. This row needs to be inserted between the first and last name rows.

Inserting a row is easy. Remember that when you create a row using the Grid designer, you are in effect splitting a row.

Steps

  • Verify the grid can grow, if not provide additional space for the new row
  • Set the target row to be split to Fixed sizing
  • Increase target row size
  • Add new row by splitting the target row
  • Set split row sizing
  • Add new controls, set control sizing, set row sizing

Before and After Inserting a New Row

BeforeandAfter

Figure 1 Before and After 

Step One – Verify the Grid Can Grow

  1. Check to see if the Grid can grow.
    1. If the Grid has a Star size row this takes care of this requirement.
    2. If not resize the container that the Grid is a child of to allow the Grid to grow in height.

Step Two – Set Target Row to be Split to Fixed Size

SettingRowToFixedSize

Figure 2 Setting Target Row to Fixed Size

  1. Using the Grid row size selector, set the row you need to split to Fixed size.

Step Three – Increase Target Row Size

InsertRowOne

Figure 3 Increase Target Row Size

  1. In the XAML editor or Properties Window, set the row height you are splitting to a higher value. For this example the row was resized to 60.

Step Four - Add New Row by Splitting the Target Row

InsertRowTwo

Figure 4 Add New Row by Splitting the Target Row

  1. Click on the Grid rail to add a new row.
    1. If you click above or below the existing controls you won't cause those controls to span across two rows.
    2. If you add the row and the Grid line is touching the existing controls, those controls will be spanned across two rows. In this case after you have inserted the new row, you'll need to also remove the Grid.RowSpan attached property from those controls.
  2. In Figure 4 above the new row was added above the existing controls in the row.
  3. When the new row is inserted, controls in higher numbered rows have their Grid.Row attached property automatically incremented.

Step Five – Set Split Row Sizes

InsertRowThree

Figure 5 Inserting Row Step Three

  1. Use the Grid row size selector and set the last name row to Auto size.
  2. Use the XAML editor or Properties Window and set the new row's Fixed size to 35.

Step Six – Add New Controls, Set Control Sizing, Auto Size Row

InsertRowFour

Figure 6 Add New Controls, Set Control Sizing, Auto Size Row

  1. Drag a Label to the first column, second row.
    1. Using the designer, resize the Label so that it fits in the first column.
  2. Using the Properties Window set the following properties on the new Label:
    1. Height to Auto
    2. Width to Auto
    3. VerticalAlignment to Center
    4. HorizontalAlignment to Stretch
    5. Margin to 3.5
    6. Content to Middle Initial
  3. Drag a TextBox to the second column, second row.
  4. Using the Properties Window set the following properties on the new TextBox:
    1. Height to Auto
    2. Width to 25
    3. VerticalAlignment to Center
    4. HorizontalAlignment to Left or Stretch. If using fixed width use Left or if using Auto width use Stretch.
    5. Margin to 3.5
  5. Using the Grid row size selector, set the new row to Auto size.
Note

The Margin of 3.5 conforms to the spacing requirements documented here:
http://msdn.microsoft.com/en-us/library/aa511279.aspx#spacing

You have just quickly inserted a new row in your data entry form.

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

How to Layout a Data Entry Form

This article has a corresponding video that can be viewed here.

The WPF & Silverlight Designer provides the ability to quickly layout a data entry form. This walk-through will provide a workflow for laying out Labels and TextBoxes using the Grid control as the layout panel.

Completed Form UserControl

UserControlLayoutComplete

Figure 1 Completed Form

Step One – Add Rows and Columns and Controls

UserControlLayoutOne

Figure 2 Data Entry Form Step One

  1. Add a new UserControl to your project.
  2. Select the root Grid by clicking inside the UserControl.
  3. Add a column by clicking on the upper Grid rail in the desired location.
  4. Add three rows by clicking on the Grid rail in the desired location.
  5. Drop the required Label controls in the first column.
  6. Drop the required TextBoxes or other controls in the second column.
Tip

Notice that the column width is 137. The default width of a Label control when added from the ToolBox is 120. Making the target column wider than the Label makes it easy to initially drop the Label control on the design surface.

The row heights are also unimportant at this stage. Creating the rows taller than the Label or TextBox control makes it easy to create the controls.

Step Two – Auto Size Label Controls

UserControlLayoutTwo

Figure 3 Data Entry Form Step Two

  1. Multi-select the Label controls by CTRL+clicking each control on the design surface or use the Document Outline.
  2. Using the Properties Window set the following properties:
    1. Height to Auto
    2. Width to Auto
    3. VerticalAlignment to Center
    4. HorizontalAlignment to Stretch
    5. Margin to 3.5
Note

The Margin of 3.5 conforms to the spacing requirements documented here:
http://msdn.microsoft.com/en-us/library/aa511279.aspx#spacing

Step Three – Auto Size TextBox Controls

UserControlLayoutThree

Figure 4 Data Entry Form Step Three

  1. Multi-select the TextBox controls by CTRL+clicking each control or use the Document Outline.
  2. Using the Properties Window set the following properties:
    1. Height to Auto
    2. Width to desired fixed value or Auto
    3. VerticalAlignment to Center
    4. HorizontalAlignment to Left or Stretch. If using fixed width use Left or if using Auto width use Stretch.
    5. Margin to 3.5

Step Four – Auto Size Rows

UserControlLayoutFourA

Figure 5 Resizing Grid Rows

  1. Resize the rows with Labels to Auto.
    1. Hover the mouse over the left grid rail.
    2. The Grid Row size selector will appear.
    3. Click on Auto.
    4. Repeat for each row.

UserControlLayoutFourB

Figure 6 Data Entry Form Step Four

Figure 6 above shows the form with each row with controls set to Auto size.

Step Five – Size Columns

UserControlLayoutFive

Figure 7 Data Entry Form Step Five

  1. Assign the Content property to each Label control.
  2. Set column one of the Grid to fixed size of 100.
    1. If you need to localize your application you can leave the Label column set to Auto size. Then when the Label text grows wider when a different language is used at runtime the Label column will automatically grow in size.
    2. If space is a consideration, the TextBlock control provides text wrapping. Using the same technique also set the MaxWidth property on the column. This will ensure that the column is never wider than this value. If the TextBlock text is wider than the MaxWidth it will wrap its text. Since the rows are Auto sized, when the text wraps that row's height will be increased to accommodate the wrapped text.
  3. Set column two of the Grid to Star size.
Note

The Grid row and column size selector does not allow changing of the numeric values for Fixed or Star sizes. Instead use the Properties Window or XAML editor.

Comments

Microsoft values you opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

WPF & Silverlight Layout Controls

The WPF and Silverlight platforms have a wide selection of powerful layout controls.

This topic will provide you with an understanding of these layout controls and how to take advantage of the WPF and Silverlight Designer features when working with these controls.

In this topic when the term pixel is used, it refers to a device-independent-pixel. In WPF a pixel is 1/96 of an inch. This MSDN topic covers device-independent-pixels. http://msdn.microsoft.com/en-us/library/bb847924.aspx

Layout Control Types

WPF layout controls can be logically grouped by base types that determine their behavior.

  1. Panels
    1. Provide arrangement of their child objects.
    2. Derive directly or indirectly from Panel.
    3. Have a Children property that is a collection of their child objects.
    4. Example controls are the Grid, StackPanel, Canvas, DockPanel WrapPanel and UniformGrid.
  2. Decorators
    1. Apply effects to their single child object.
    2. Derive from Decorator.
    3. Have a Child property that contains their single child object.
    4. Example controls are the Border and ViewBox.
  3. Content Controls
    1. Contain a single object of any type.
    2. Derive directly or indirectly from ContentControl.
    3. Have a Content property that contains their single object.
    4. Example controls are the Window, UserControl, GroupBox, TabItem, Expander, HeaderedContentControl and ContentControl.
  4. Items Controls
    1. Used to present a collection of objects.
    2. Derive directly or indirectly from ItemsControl.
    3. Have two ways of being populated
      1. Objects can be added to the Items property in code behind or in XAML.
      2. A list of objects can be bound to the ItemsSource property.
    4. When objects are added using either of the two above methods, UI objects will be automatically generated. The generated UI objects can be customized through the use of DataTemplates.
    5. Example controls are the ListBox, ListView, DataGrid, TabControl, ComboBox, Menu and ItemsControl.
      1. Note the DataGrid and Menu will be covered in a future article.

Panel Selection

Panel Description Good For
Grid Provides flexible grid area that consists of rows and columns. Overall application layout, data entry forms
Canvas Supports absolute positioning of child elements Good for drawings, not great for dialogs as there is no support for reliability, and limited support for Auto sizing
StackPanel Supports flow like positioning of child elements in a horizontal or vertical direction Good for lists of items.
For situations where you want more fine-tuned control of sizing relationships, use a grid instead.
Instead of using a StackPanel as ItemsControl ItemsPanel, use the VirtualizingStackPanel instead as it will yield much better performance for large lists of items.
WrapPanel Similar to StackPanel, but wraps the content when it reaches a boundary Good for lists of items, though it does not support virtualization
UniformGrid Divides the space equally into rows and columns, placing each child in a separate cell Good for tiling in a ItemsControl, though it does not support virtualization
Dock Panel Aligns content to edges of its container. Content can also be set to fill the remaining space For better designer support use a Grid

Grid

The Grid control provides a flexible grid area that consists of rows and columns. Flexible row and column sizing options enable the grid to predictably size and resize itself at design time or runtime as its parent control is resized.

GridLayout

Figure 1 Grid Layout

Grid Row and Columns

Rows are added to the grid by adding a RowDefinition to the RowDefinitions collection. The grid in Figure 1 above has three rows defined.

Columns are added to the grid by adding a ColumnDefinition to the ColumnDefinitions collection. The grid in Figure 1 has two columns defined.

Row and Column Definition Sizes

The Grid row Height and Grid column Width properties are of type GridLength. The GridLength allows for flexible property value assignment.

  1. Star sizing
    1. Is expressed as a weighted proportion of available space.
    2. In Figure 1 the last two rows use Star sizing. The middle row (2*) will be giving twice the layout space as the last row (*). By looking at the left grid rail, you can see that the middle row has been allocated 80 pixels and the bottom row has been given 40 pixels.
    3. Row or columns that are Star sized will resize at runtime if their parent Grid is resized.
    4. Star sizing is the default mode for row and column definitions if no height or width is provided.
  2. Fixed
    1. Numeric value of type Double that defines size in pixels.
    2. Value can be qualified to allow sizing to be determined in points, inches or centimeters. Example: 14pt, 2in or 5cm. The default is pixel sizing. 75px is equivalent to 75.
    3. In Figure 1 the first column uses Fixed sizing.
  3. Auto
    1. Sizing is determined by the size of its contents. In Figure 1, the first row is Auto sized and its height is determined by the height of its contents; in this case the two Label controls.
    2. Auto sized rows or columns that have no content consume no space on the design surface.
    3. However, the row or column handle is still visible and can be used to resize the row or column as in Figure 2 below. The red arrow points to the Auto sized column handle.

    AutoSizedColumnAdorner

    Figure 2 Auto Sized Column Handle

Design Time Size Information

The numeric values displayed in the Grid control's rail is the actual design time size in pixels of the row or column. This is true for both Fixed size and Star sized rows or columns.

Note

If the Auto Sized Grid is hosted in a Window, the indicated values for height and width may be different at runtime based on the Window chrome.

Positioning Controls in a Grid

The Grid control lays out controls based on several attached properties.

Information

See MSDN documentation on Attached Properties here: http://msdn.microsoft.com/en-us/library/ms749011.aspx

GridAttachedProperties

Figure 3 Grid Attached Properties

In Figure 3 above the Grid has three rows and two columns defined. The child controls as laid out according to the attached properties.

  • Grid.Row – assigns the row the control will be rendered in (default is row 0)
  • Grid.Column – assigns the column the control will be rendered in (default is column 0)
  • Grid.RowSpan - indicates the total number of rows that the control spans within the Grid (default is row 0)
  • Grid.ColumnSpan - indicates the total number of columns that the control spans within the Grid (default is row 0)

Grid Design Time Features

The WPF Designer operates on rows and columns in a similar manner. Examples and text will not be repeated for row and columns. Where designer behavior differs between rows and columns that information will be provided.

Adding Rows or Columns using the WPF Designer

AddingGridRow

Figure 4 Add Grid Row

  1. With the Grid control selected in the designer, you can add rows by hovering the mouse over the left grid rail and clicking the rail in the desired location as in Figure 4 above.
  2. Clicking on the left rail splits the row into two rows.
    1. If the row is Star sized, the row will be split leaving two Star sized rows.
    2. If the row is Fixed sized, the row will be split leaving two Fixed sized rows.
    3. If the row is Auto sized, the row will be split leaving two Fixed sized rows.
  3. Columns are added using the top grid rail using same technique as the rows.

Resizing Rows and Columns with the WPF Designer

The WPF Designer provides two techniques for resizing a row or column.

  • When resizing by dragging the row or column handle, the designer will maintain the size of the child controls
  • When resizing by dragging the row or column line, the designer will maintain the margins of the child controls

Resizing a Row Containing an Auto Sized Control without Changing the Control Size

PreserveSizeResize

Figure 5 Maintain Control Size Resize

Dragging the row handle (triangle) enables row resizing without changing the Button size.

Resizing a Row Containing an Auto Sized Control without Changing the Control Margins

PreserveMarginResize

Figure 6 Maintain Control Margin Resize

Dragging the row grid line maintains the Button's margins which results in the Button resizing.

Resizing and Dropping Grid Line on Fixed Sized Control While Maintaining Control Size

PreserveSizeTopLeftAlignedControl

Figure 7 Dropping Grid Line on Fixed Sized Control

Figure 7 above displays the results of resizing a column and dropping the grid line on top of a Fixed sized control (control aligned Top & Left). Dragging the column handle resulted in the Button control maintaining its size. This was accomplished by spanning the Button across two columns.

Resizing and Dropping Grid Line on Fixed Sized Control While Maintaining Control Margins

 PreserveMarginTopLeftAlign

Figure 8 Dropping Grid Line on Fixed Sized Control

Figure 8 above displays the results of resizing a column and dropping the grid line on top of a Fixed sized control (control aligned Top & Left). Dragging the column line resulted in the Button control being clipped since size was not being maintained. To maintain sizes, use the column handle instead of the column row when resizing as in Figure 7 above.

Deleting Rows and Columns with the WPF Designer

DeletingGridRow

Figure 9 Deleting Grid Row

To delete a row or column drag the row or column header away from the grid and release the left mouse button. Notice the delete row drag icon in Figure 9 above in the center grid.

The right grid in Figure 9 shows the results of deleting the second row. The grid now has two rows and the Button control that was in Grid.Row 1 is now in Grid.Row 0.

In a row or column delete operation, the WPF Designer will renumber all affected control's Grid.Row or Grid.Column attached properties. Margins will be adjusted to maintain control positioning unless the control alignment is centered, in that case the control will remain centered.

Adding Rows and Columns using the Properties Window

Rows and columns can be added and removed from a Grid by editing the RowDefinitions or ColumnDefinitions collections using the Properties Window.

RowColumnDefinitionCollections

Figure 10 Properties Window

With the Grid control selected, using the Properties Window search box, enter "def" and the RowDefinitions and ColumnDefinitions collections will be visible.

Clicking on the ellipsis button will open a collection editor for adding, removing or reordering row or column definitions. Figure 11 below shows the ColumnDefinitions collection editor.

ColumnDefinitionsCollectionEditor

Figure 11 ColumnDefinitions Collection Editor

The ColumnDefinitions collection editor allows editing each of the ColumnDefinition properties. In addition to the Width property which is currently set to 68*, the MinWidth and MaxWidth properties are sometimes used by developers to provide a size range for the column by restricting the column's minimum and/or maximum width.

A ColumnDefinition can be added or removed from the ColumnDefinitions collection using the Add or Delete button.

Important

When using the Collection Editor and a ColumnDefinition is deleted, the Grid.Column attached property value is not adjusted like it is when using the WPF Designer.

ColumnDefinitions can be reordered using the up or down arrows.

Important

When using the Collection Editor and ColumnDefinitions are reordered, only the ColumnDefinitions are reordered. The Grid.Column attached property value is not changed for any control.

RowDefinitions have a collection editor similar to the ColumnDefinition editor.

Drag Drop and Drag Move Visual Clues

The WPF Designer provides visual clues when creating child controls by dragging and dropping from the ToolBox. These same visual clues are displayed when performing a drag move operation on the design surface.

DragDropCreateFromToolBox

Figure 12 Drag Drop from the ToolBox

All WPF controls that allow the dropping of child controls will display a blue border around themselves when a control is being dragged over them. This blue border indicates that this control will be the parent of the control being dragged if it's dropped. Additionally the target control is colored white and other areas on the design surface outside the control are shaded.

The Grid has an enhanced drag over behavior. The cell that the mouse is over will be white and the rest of the design surface will be shaded as in Figure 12 above.

If the control being dragged would span multiple rows or columns, the additional rows or columns will also be white and not shaded.

Grid.IsSharedSizeScope

The Grid control has a unique feature that allows either rows or columns to be automatically sized to the largest row or column in their SharedSizeGroup. The SharedSizeGroup scope is determined by the attached property Grid.IsSharedSizeScope.

GridSharedSizeScope

Figure 13 Grid.IsSharedSizeScope

In Figure 13 above the three ColumnDefinitions are participants of the SharedSizeGroup "buttons." The scope of their size sharing is the immediate parent Grid control. The parent Grid control has the attached property Grid.IsSharedSizeScope set to True. This establishes this Grid control as a shared size scope.

Each of the columns will automatically size to the largest column width in the SharedSizeGroup. In Figure 13 the Button "Long Button Name" is the widest Button control. Since the other two Button controls are using auto sizing, they will grow as their column resizes to match the widest column in the SharedSizeGroup.

Multiple Grid Controls Sharing the Same Shared Size Scope

MultipleGridsSharingSameSharedSizeScope

Figure 14 Multiple Grids Sharing the Same Shared Size Scope

Figure 14 above shows multiple Grid Controls sharing the same shared size scope. This is accomplished by nesting Grid Controls.

The outer Grid has the Grid.IsSharedSizeScope attached property set to True.

The nested child Grid rows or columns can now participate in the same SharedSizeGroup.

In Figure 14 the two Grid control's columns will all be the size of the widest column in the SharedSizeGroup "buttons."

Runtime Resizing of Grid Rows and Columns

The GridSplitter control provides runtime resizing of the Grid control's rows or columns.

GridSplitter

Figure 15 GridSplitter

In Figure 15 the GridSplitter is located in Grid.Column zero and aligned to the right of the column. The GridSplitter control can also be placed in its own row or column.

After adding the GridSplitter control to the Grid, use the Properties Window or the XAML editor to set the required properties on it.

At runtime the user will be able to resize the columns by dragging the GridSplitter left or right.

StackPanel

The StackPanel arranges child elements into a single line that can be oriented horizontally or vertically.

StackPanelVertical

Figure 16 StackPanel with Vertical Orientation

Figure 16 above shows the default orientation of the StackPanel, vertical.

StackPanelHorizontal

Figure 17 StackPanel with Horizontal Orientation

Figure 17 above shows the StackPanel with its Orientation property set to Horizontal.

StackPanelReOrdering

Figure 18 StackPanel Child Control Reordering

The StackPanel control has a design time experience that displays a position line when dragging controls into the StackPanel or when dragging controls to reorder them.

In Figure 18 above Button B is being dragged below Button C. The three above image display before, during and after the drag operation.

Notice the blue border and white drop surface applied to the drop target StackPanel and the shading outside the StackPanel control.

Canvas

The Canvas defines an area which you can explicitly position child elements by using coordinates that are relative to the Canvas area.

Canvas

Figure 19 Canvas

When controls are placed on a Canvas, the Margin, Vertical and Horizontal alignment properties do not play a part in the control's layout. Instead the Canvas uses the attached properties Canvas.Left and Canvas.Top determine child control positioning. In Figure 19 the Canvas.Left and Canvas.Top attached properties are highlighted.

DockPanel

The DockPanel defines an area where you can arrange child elements either horizontally or vertically, relative to each other.

DockPanel

Figure 20 DockPanel

Except for adding controls to the DockPanel, the WPF Designer does not provide additional design time help. After adding controls to the DockPanel, use the Properties Window or the XAML editor to set the properties on the child controls.

The location of the DockPanel child controls is determined by the attached property DockPanel.Dock. Controls can by docked, left, top, right or bottom.

By default the DockPanel will allocate all remaining space to the last child added to it. In Figure 20 above you can see how the last Button control has consumed the remaining space of the DockPanel.

The secret to using the DockPanel is to add the outer controls to the DockPanel first. Note the order the controls are added in the XAML. The last control you add should be the control that will consume the remaining space.

WrapPanel

The WrapPanel positions child elements in sequential position from left to right, breaking content to the next line at the edge of the containing box. Subsequent ordering happens sequentially from top to bottom or from right to left, depending on the value of the Orientation property.

WrapPanel

Figure 21 WrapPanel

Except for adding controls to the WrapPanel, the WPF Designer does not provide additional design time help.

When the WrapPanel is resized at runtime, it will automatically lay its child controls out again.

Child controls can be laid out horizontally or vertically by setting the Orientation property.

A real world example of using the WrapPanel would be the Windows Control Panel. With each icon and text being wrapped in its own panel, those panels would be added to the WrapPanel to provide flexible layout repositioning at runtime as the Control Panel is resized.

UniformGrid

The UniformGrid provides a way to arrange content in a grid where all the cells in the grid have the same size.

UniformGrid

Figure 22 UniformGrid

Except for adding controls to the UniformGrid, the WPF Designer does not provide additional design time help.

Each of the controls in Figure 22 above has the same space allocated to them.

The UniformGrid provides properties for setting the desired number of row and columns if the default layout does not suit your application's needs.

Panel.ZIndex Attached Property

Before looking at some additional layout panels, let's cover a layout attached property that is exposed by the Panel class that all panels derive from.

The Canvas is a panel so this attached property applies to the Canvas as well as other panels.

Stacking Order for Panel Child Controls

The Panel.ZIndex attached property is used by all panel controls to determine the stacking order of controls laid on top of one another.

CanvasStackingOrder

Figure 23 Control Stacking Order

Note

The Panel.ZIndex property can be set on child controls of all panels. This example is showing the Panel.ZIndex attached property being used with the Canvas.

Normally the control stacking order is determined by the order that the controls are added to the layout.

In Figure 23 above buttons A, B and C were added in the order they appear in the XAML.

However Button B is rendered on top of Button C. This is because the Panel.ZIndex attached property for Button C has been set to a lower value than the Panel.ZIndex attached property for Button B.

The default value of the Panel.ZIndex attached property is zero. You can assign positive or negative values to this attached property to get the stacking order your application requires.

Border

The Border control draws a border, background, or both around another element.

Border

Figure 24 Border

Except for adding a single child control to the Border, the WPF Designer does not provide additional design time help.

In Figure 24 above, the StackPanel is the single child control of the Border.

Commonly set Border Properties

  • Margin provides spacing around the Border.
  • Padding provides spacing between the Border's border and the child control.
  • BorderThickness is of type Thickness and gives the border edges their thickness.
  • BorderBrush gives the border its color.
  • CornerRadius gives the Border the rounded corners.
  • Background can also be set to provide a background color for the Border and its child control.

Window

The Window control provides the ability to create, configure, show, and manage the lifetime of windows and dialog boxes.

Window

Figure 25 Window

Except for adding a single child control to the Window and the size mode button, the WPF Designer does not provide additional design time help.

WPF applications each have one or more windows. Since a Window control can only contain a single control, the content of a Window control is normally a layout panel to enable the layout of many additional controls.

The size mode button was covered in the Setting Up Visual Studio for WPF and Silverlight Development article.

UserControl

The UserControl provides a simple way to create a control or extract out a set of controls for reuse.

UserControl

Figure 26 UserControl

Except for adding a single child control to the UserControl and the size mode button, the WPF Designer does not provide additional design time help.

Since a UserControl can only contain a single control, the content of a UserControl is normally a layout panel to enable the layout of many additional controls.

The UserControl size mode defaults to Auto size.

The size mode button was covered in the Setting Up Visual Studio for WPF and Silverlight Development article.

GroupBox

The GroupBox is a control that creates a container that has a border and header for its single content object.

GroupBox

Figure 27 GroupBox

Except for adding a single child control to the GroupBox, the WPF Designer does not provide additional design time help.

In Figure 27 above, the StackPanel is the single child control of the GroupBox.

When dragging a GroupBox from the ToolBox, the default child control for the GroupBox is a Grid. In Figure 27, the Grid has been replaced with a StackPanel.

Commonly set Border Properties

  • Margin provides spacing around the GroupBox.
  • Padding provides spacing between the GroupBox's border and the child control.
  • BorderThickness is of type Thickness and gives the border edges their thickness.
  • BorderBrush gives the border its color.
  • Header typically provides text at the top left of the GroupBox. However, the Header property is not limited to just text as it's of type Object. The Header can contain any single WPF control.
    • An example of a non-standard Header could be a StackPanel that contains an Image control and a TextBlock control.
  • Background can also be set to provide a background color for the GroupBox and its child control.

Expander

The Expander control displays a header that has a collapsible window that displays content.

Expander

Figure 28 Expander Control Expanded

At design time, when the Expander control is selected it will expand. This provides access to its single child control. The child control is typically a panel. The default panel is the Grid control. In Figure 28 above the Grid was replaced with a StackPanel.

The Header property typically provides text at the top of the Expander. However, the Header property is not limited to just text as it's of type Object. The Header can contain any single WPF control. An example of a non-standard Header could be a StackPanel that contains an Image control and a TextBlock control.

ExpanderCollapsed

Figure 29 Expander Control Collapsed

Selecting another control outside the Expander will cause the Expander to collapse as pictured in Figure 29 above.

TabItem

The TabItem control represents a selectable item inside a TabControl.

TabItem

Figure 30 TabItem

The TabControl contains one or more TabItem controls that the user can select at runtime. The TabItem control typically contains a single panel child control that is used to layout additional controls.

The default panel for the TabItem when added from the TabControl Context Menu is the Grid control as pictured in the XAML in Figure 30 above.

WPF: At design time in you can select the TabItem you need to layout by clicking on its Header.

The Header property typically provides text for the TabItem Header. However, the Header property is not limited to just text as it's of type Object. The Header can contain any single WPF control. An example of a non-standard Header could be a StackPanel that contains an Image control and a TextBlock control.

TabControl

The TabControl is a control that contains multiple items that share the same space on the screen and is pictured in Figure 30 above.

The TabControl TabStripPlacement property determines the location of the TabItem Headers. The default value is Top. Other possible locations are Left, Right and Bottom.

TabItemAddingWithContextMenu

Figure 31 Adding TabItem using TabControl Context Menu

At design time additional TabItem controls can be added to the TabControl by selecting the TabControl, right clicking to bring up the Context Menu and selecting Add Tab as pictured in Figure 31 above. In Figure 31 the mouse was right clicked when the mouse cursor was in the white space to the right of TabItem2's Header.

TabItemAddingWithCollectionEditor

Figure 32 Adding TabItem using Properties Window

At design time additional TabItem controls can also be added, removed and reordered by using the TabControl Items property Collection Editor as in Figure 32 above.

Layout Properties

The following section briefly covers common properties that affect layout.

Margin

The Margin property is of type Thickness and provides spacing from the control's outer edge to other controls around it.

VerticalAlignment

  • Top – control is aligned to the top of the parent's layout slot.
  • Center – control is aligned to the center of the parent's layout slot.
  • Bottom – control is aligned to the bottom of the parent's layout slot.
  • Stretch – control stretches to fill the parent's layout slot.
HorizontalAlignment 
  • Left – control aligned to the left of the layout slot for the parent element.
  • Center – control aligned to the center of the layout slot for the parent element.
  • Right – control aligned to the right of the layout slot for the parent element.
  • Stretch – control stretched to fill the entire layout slot of the parent element.

Visibility

  • Visible – display the control.
  • Hidden – do not display the control, but reserve space it in layout.
  • Collapsed – do not display the control, and do not reserve space for it in layout.

Visibility

Figure 33 Visibility

In Figure 33 above the left Widow shows the design time rendering of controls on the design surface. Regardless of the Visibility property, all controls are rendered on the design surface.

In Figure 33 above the right Window shows the runtime rendering of controls with the different Visibility property values set.

ClipToBounds

The ClipToBounds property indicates whether to clip the content of this control (or content coming from the child elements of this control) to fit into the size of the containing element.

ClipToBounds

Figure 34 ClipToBounds

In Figure 34 above the top TextBox extends past the boundary of its parent Canvas control.

In Figure 34 above the bottom Canvas has its ClipToBounds property set to True. This results in the bottom TextBox being clipped at the boundary of its parent Canvas control.

Comments

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above feature enables your workflow
  • What is missing from the above feature that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Visual Studio Cider Team

More Posts Next page »
Page view tracker