XAML Guidelines for Creating a Composite UI

This topic describes some useful considerations when designing user interfaces (UI) for composite applications. This applies to anyone creating XAML for Composite User Interfaces in WPF or Silverlight.

Prerequisites

To fully understand the guidance provided in this topic, it is recommended that you have knowledge in the following areas in WPF and Silverlight:

  • Composite application
  • Regions
  • User controls
  • Creating custom user controls
  • Data templates
  • Presentation model
  • Resources

For more information about these topics, see UI Design Guidance Overview.

Guidelines for Creating XAML

The following sections provide tips that you should consider when designing the user interface (UI) or user controls.

Note

The following concepts are used widely in this section:
View: A view encapsulates a portion of your user interface that you would like to keep as decoupled as possible from other parts of the application. You can define a view as a user control, data template, or even a custom control.
Region: Region manages the display and layout of views. Regions can be accessed in a decoupled way by their name and support dynamically adding or removing views. A region is typically a hosting control. Think of regions as containers where views will be dynamically loaded.

Layout

Consider the following tips when designing the layout of a composite application:

  • The shell defines the main layout of the application. Each area of the layout is a region and should be kept as empty containers. Do not place content inside regions because content will be loaded there at run time.
  • The shell should contain the background, titles, and the footer. Think of the shell as an ASP.NET master page**.**
  • Control containers that act as regions are decoupled from the views they contain; therefore, you should be able to change the size of the views without modifying the controls or change the size of the controls without modifying the views. You should consider the following when defining the view's sizes:
    • If a view will be used in several regions or it is uncertain where it will be used, design it with dynamic width and height.
    • If the views have fixed sizes, the regions of the shell should use dynamic sizes.
    • If the Shell regions have fixed sizes, the views should use dynamic sizes.
    • Sometimes the views may require a fixed height and dynamic width. An example of this is the PositionPieChart view located in the sidebar of the Stock Trader Reference Implementation (Stock Trader RI).
    • Other views may require a dynamic height and width**.** For example, the NewsReader view in the sidebar of the Stock Trader RI. The height itself depends on the title's length, and the width should always adapt to the region's size (sidebar width). The same applies to the PositionSummaryView view, where the grid's width should adapt to the screen size and the height should adapt to the number of rows in the grid.

Animation

Consider the following tips when animating the shell or the views:

  • The layout of the shell can be animated but its contents and views must be animated separately.
  • Design and animate each view separately.

View

Each UI element in a composite application must be designed separately. This makes it hard to visualize the composite page or window. To visualize the composite view, you should consider doing the following:

  • Create a test project with a simple page or window that contains all the UI elements for the view you want to test.
  • Work with the developer to define mock data to be displayed for each UI element in this simplified page or window. For more information, see the section "Considerations for Developers" later in this topic.

Optimization

Consider the following tips for performance optimization:

  • Any common resource along all views should be placed in the App.xaml file (or merged dictionaries in WPF) to avoid duplicating the styles, but it is recommended to do this after the module's view is completely designed. Having the application resources in the main App.xaml file breaks the design view in Microsoft Expression Blend; therefore, the view may not be displayed properly if the module is tested by itself. It is better to leave this task for the end of the design phase.

  • In Silverlight, avoid using non-system fonts for specific static text that should be styled differently from the rest of the application (for example, the application title). In such case, analyze if it is better to convert the text to curves or to embed the font.

    Note

    For more details about this, see Using Custom Fonts in Silverlight.

Creating Mock Data to Display in Expression Blend

One of the most important challenges you may face is designing the layout of a composite application and its components with a designing tool, such as Expression Blend. The reason for this is that most views will be loaded to their corresponding containers at run time. Use the following tips to display mock data in Expression Blend. This example uses the WatchListView view, located in the Watch module of the Stock Trader RI.

If you load the WatchListView in Expression Blend, as it is now, you will see only the headers of the grid, as shown in Figure 1.

Ff921166.cde08fa7-c1ab-4d6c-909f-2523a97b9746(en-us,PandP.20).png

Figure 1

The WatchListView loaded in Expression Blend

To enable the views to show mock data when loaded in Expression Blend

  1. Expression Blend renders elements defined in XAML through their default constructor, and in composite applications, the separated presentation patterns are used broadly to define views. Therefore, a good recommendation is to create a default constructor of the presentation model (or any view model used). This default constructor should be used to populate mocked data into the view. The following code shows a sample default Presentation Model constructor that is populated with mocked data.

    public WatchListPresentationModel()
    {
        this.HeaderInfo = Resources.WatchListTitle;
        this.WatchListItems = new ObservableCollection<WatchItem>();
        this.WatchListItems.Add(new WatchItem("STOCK60", 25.6m));
    }
    
  2. It is recommended that you use conditional compiling, so this default presentation model constructor is only used when you are, for example, in "Design mode."

    The following code shows the default WatchList presentation model inside a conditional compiling clause; therefore, this constructor will only be used when the DESIGN constant is defined.

    #if DESIGN
            public WatchListPresentationModel()
            {
                this.HeaderInfo = Resources.WatchListTitle;
                this.WatchListItems = new ObservableCollection<WatchItem>();
                this.WatchListItems.Add(new WatchItem("STOCK60", 25.6m));
            }
    #endif
    

    To define the DESIGN constant, right-click the project name where you are using this conditional compilation symbol (StockTraderRI.Modules.Watch in this example), click Properties, and then click the Build tab. In the Conditional compilation symbols box, type DESIGN to define the constant, as shown in Figure 2.

    Ff921166.1fa573e9-2b90-4e12-9140-73b3aa374c0c(en-us,PandP.20).png

    Figure 2

    Defining a conditional compilation constant

    Note

    This will affect the Debug configuration. When building in Release mode, this symbol will not be defined, so the default constructors with mocked data will not be part of the compilation results.
    When the design phase is over, it might be a good idea to remove the conditional compilation symbol from the Debug configuration also, to avoid this extra code being compiled if the deployment is ever mistakenly done in Debug mode.

  3. The reference implementation uses the presenter-first approach to create the view and the PresentationModel. After the view is created, the PresentationModel is assigned to the Model property (which is just a typed wrapper of DataContext). Because this latter step is not executed in design-time inside Expression Blend, remember to set the presentation model as the view's data context in XAML to populate the view with the mocked data. If you defined a Model property in your user control, you can set the presentation model to this property.

    The following XAML markup shows how to set the presentation model as the data context.

    <UserControl x:Class="StockTraderRI.Modules.Watch.WatchList.WatchListView"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Converters="clr-namespace:StockTraderRI.Infrastructure.Converters;assembly=StockTraderRI.Infrastructure"
        Height="Auto" Width="Auto">
        <UserControl.DataContext>
            <WatchListPresentationModel/>
        </UserControl.DataContext>
        ...
    </UserControl>
    

    Note

    When the styling for the view is complete, make sure you remove this declaration from the XAML. If it is not removed, the mocked data will appear at run time, and will cause errors if compiled in Release mode, because there will be no default constructor for the presentation model in this mode.

After performing the previous steps, if you reload the view in Expression Blend, it will be populated with the mocked data, as shown in Figure 3.

Ff921166.a72a5949-ec1b-4deb-921e-b1328dfdae99(en-us,PandP.20).png

Figure 3

The WatchListView loaded in Expression Blend

Doing this results in more work for developers, but it simplifies the designers' task and integration processes, because they can see and design the views as they will be shown in the running application.

More Information

For more information about user interface layout, visual representation, data binding, resources, and presentation model for the XAML developer, see the UI Design Guidance Overview.

Home page on MSDN | Community site