What can I say?

  • Displaying hierarchical data in the DataGrid

    The attached project shows how to display data which is both tabular and hierarchical in nature in the Silverlight (or WPF) DataGrid. Employee list is an example of such data, where each employee is described using the same set of data column but there is also a reporting relationship between employees and their managers (also employees). The implementation uses DataGrid's functionality to load and display individual rows and columns. It then adds some special UI and functionality to handle the TreeView-like functionality for expanding and collapsing hierarchical relationships between rows. The latter is accomplished through the following:

    1.       Data is exposed to the UI through a set of presenters, which describe both the tabular and hierarchical nature of the data model (GridDef, RowDef and ColumnDef classes).

    2.       The first column in the DataGrid is defined as DataGridTemplateColumn.

    3.       The column template consists of three components, each databound to a property of the row definition (RowDef):

    1.       A checkbox. Its IsChecked property is bound to the IsExpanded property of the row definition. Its margin property is bound to the row’s HierarchyLevel property (through a converter which converts sequential level to a Thickness structure).

    2.       TextBlock or other element bound to the tabular valu of the first column (e.g. employee name).

    4.       The checkbox in the above template is re-templatized so that instead of showing the usual rectangle, swish and other content, it only shows a triangle pointing down or to the side or nothing at all depending on whether the checkbox’s IsChecked property is true, false or null.

    5.       The implementation of the IsExpanded property sets or resets row’s IsVisible property (a local property, not a UI property).

    6.       The GridDef object (main presenter) has a Display method, which returns an IEnumerable. It iterates over the data and returns (though the yield statement) currently visible rows.

    In a future blog I will suggest an implementation to handle sorting functionality.

  • WPF and Silverlight working together presentation

    I recently gave a presentation to a number of ISV regarding use of WPF and Silverlight 2 for developing applications that can be deployed to both the desktop and the web. The attached presention and demos show the main similarities and differences between the two frameworks and provide an example of a shared application.

  • Custom data and dynamic templates in WPF

    This blog describes how TemplateSelector in WPF can be used to dynamically modify contents of the UI. This is particularly useful in a common scenario many ISV's need to support: ability of 3rd parties and users to extend the ISV's data model with their own data columns.

    For example, the original application may include a Product table with some columns (e.g. Id, Name, etc.). However, application's users may want to extend that definition to include additional columns. One of the issues that presents is using the data in UI: the UI provided by the ISV obviously has no notion of the new data columns. WPF, through template selector functionality allows the ISV to include these items in their UI.

    One of the options on data binding is the specification of a template selector. Template selector is a custom class derived from DataTemplateSelector, which implements a method returning a DataTemplate given reference to the data that needs to be presented. The method can return an existing data template but it can also construct a new data template dynamically and return it. It is the last option that is particularly useful in the ISV scenario. The custom selector can dynamically discover the new columns added by the user, possibly collect additional meta-data about them (from SQL or some other proprietary mechanism used by the ISV) and return a data template, which provides a mapping of the data columns to WPF UI elements.

    The attached sample shows how this can be done. For simplicity's sake the sample generates all its source data. Note that the recommended way of creating the new data template is by constructing xaml and using XamlReader. (The alternative, using the DataTemplate class, populating it with data, etc. is not recommended).

     

  • Editable ListBox using template

    WPF Templates are useful for defining common themes and styles. They can also be used to extend the functionality of controls. Following is an example of a ListBoxItem template, which makes individual items in a listbox in-place editable (provided the listbox contains strings only). To achieve this effect, the standard ListBoxItem template is modified as follows (note, to achieve similar effect with Win32 ListBox would require significant amount of procedural code):

    • Instead of just having a ContentPresenter (to show the content), the modified template has a ContentPresenter and a TextBox, the latter overlaying the first. Initially the TextBox is in Collapsed state (invisible and not occupying any space).
    • The template includes a property trigger based on IsSelected property. The trigger modifies the setting of the TextBox defined above to make it visible.
    • The trigger also databinds the content of the TextBox to the listbox item's content using the RelativeSource source reference.

    The downside of this approach is that the logical tree now contains an additional control (TextBox) for each item in the listbox item, which if the listbox is bound to a large collection could have performance implications.

    <Page
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Xml Data Binding" FontSize="20"
        >
      <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
          <Style x:Key="{x:Type ListBoxItem}" TargetType="{x:Type ListBoxItem}">
            <Setter Property="Template">
              <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                  <Grid>
                    <ContentPresenter />
                    <TextBox Name="EditableText" Visibility="Collapsed"/>
                  </Grid>
                  <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="true">
                      <Setter TargetName="EditableText" Property="Visibility" Value="Visible" />
                      <Setter TargetName="EditableText" Property="Text" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"/>
                    </Trigger>
                  </ControlTemplate.Triggers>
                </ControlTemplate>
              </Setter.Value>
            </Setter>
          </Style>
        </StackPanel.Resources>
        <ListBox Width="100" Height="155">
          <ListBoxItem>Item 1</ListBoxItem>
          <ListBoxItem>Item 2</ListBoxItem>
          <ListBoxItem>Item 3</ListBoxItem>
          <ListBoxItem>Item 4</ListBoxItem>
          <ListBoxItem>Item 5</ListBoxItem>
          <ListBoxItem>Item 6</ListBoxItem>
          <ListBoxItem>Item 7</ListBoxItem>
          <ListBoxItem>Item 8</ListBoxItem>
          <ListBoxItem>Item 9</ListBoxItem>
          <ListBoxItem>Item 10</ListBoxItem>
        </ListBox>
        <ListBox Width="100" Height="155">
          <ListBoxItem>Item 1</ListBoxItem>
          <ListBoxItem>Item 2</ListBoxItem>
          <ListBoxItem>Item 3</ListBoxItem>
          <ListBoxItem>Item 4</ListBoxItem>
          <ListBoxItem>Item 5</ListBoxItem>
          <ListBoxItem>Item 6</ListBoxItem>
          <ListBoxItem>Item 7</ListBoxItem>
          <ListBoxItem>Item 8</ListBoxItem>
          <ListBoxItem>Item 9</ListBoxItem>
          <ListBoxItem>Item 10</ListBoxItem>
        </ListBox>
      </StackPanel>
    </Page>

  • A role-based approach to architecting WPF (and Silverlight 2?) applications

    Karsten Januszewski and Jaime Rodriguez in The New Iteration (http://windowsclient.net/wpf/white-papers/thenewiteration.aspx) point out the ability of WPF infrastructure (framework and tools) to allow for clear separation between the roles of designers and programmers. They also describe various development workflows this separation supports. I have been experimenting with an approach that separates the roles further and provides more detailed workflow definition.

    Roles

    The approach allows five distinct roles to cooperate in the development process: architect, developer, designer, tester and UI stylist:

    Architect defines the main components of the UI in terms of class interfaces and how they relate to each other. He/she breaks down the application into Views, Presenters and Data providers. Views will be implemented as User Controls or Windows, Presenters and Data Providers as regular, non-WPF specific classes. The definition is expressed as one or more VS.NET projects containing the definition of these interfaces.

    Tester defines the unit tests and test cases exercising these interfaces.

    Developer writes the code implementing the above interfaces, providing both UI specific and business specific logic (in separate classes).

    Designer determines the layout logic, i.e. the type of layout containers and controls needed. It’s important that the designer limits his/her work to just the choice of the type of controls and how they contain each other NOT to their actual sizing or placement in terms of margins/paddings/widths, etc. That work will be done later by the UI Stylist. The Designer also uses data-binding to define data movement between the UI and the Presenter interfaces defined by the Architect. He/she also adds the references to the events exposed by the View interfaces.

    UI Stylist completes UI design primarily in terms of esthetics and usability: adds layout parameters (e.g. margins, min/max sizes, alignments), modifies appearance of controls (styles, templates) and other parameters which do not affect the functionality (particularly code) of the application.  UI Stylist creates Resource Dictionaries.

    Components

    This approach uses the following concepts typically found in UI applications: View, Presenter, and Data Provider (references to Silverlight are to Silverlight 2 beta).

    View is a class derived from a FrameworkElement (usually UserControl); it is usually compiled from XAML and code-behind. The View class exposes WPF/Silverlight events using a WPF/Silverlight-independent delegate. These are then consumed by the Presenter, which in turn uses them to operate on the Data Provider. There is a 1:1 relationship between a View and a Presenter, although both may in turn be broken down into other Views and Presenters.

    Presenter is a class that marshals data from and to data providers. It shields the View from knowing the data provider format and behavior and vice versa. It usually has no knowledge of WPF or Silverlight, though it may make use such generic classes as Brushes for colors. In this approach, the View creates the relavant presenter as its Data Context at load time.

    Data Provider is a class or collection of classes that handle movement of data to and from the application (to database, WCF service, etc.).

    Workflow

    This development approach is broken into five steps.

    Step

    Role

    Activity

    Tool

    1

    Architect

    Factor applications into views, presenters and data providers. Use .NET interfaces to identify their properties, events, methods.

    VS.NET Class Diagram

    2

    Developer

    Generate empty classes supporting these interfaces

    VS.NET Implement Interface

    3a

    Developer

    Complete development of above classes. Assumes that the View creates and saves a reference to appropriate Presenter in the View’s data context.

    VS.NET C#/VB.NET class library development

    3b

    (parallel with above)

    UI Designer

    Design user controls implementing the above views: identify layout containers and place controls within them (DO NOT SPECIFY LAYOUT DETAILS, e.g. Left/Right/Size/Margin – make them Auto). Set the View’s Data Context to a new instance of appropriate Presenter. Use databinding to move data between the view and related presenter. Associate relevant event handler names (defined for each view) with events exposed by individual controls.

    Expression Blend

    4

    Tester

    Integrate output from 3a and b: i.e. replace empty classes developed in 2 with those developed in 3a, and test.

    VS.NET Test Edition

    5

    UI Stylist

    Add style definitions to application and/or individual user controls. Insert them into appropriate resource bags. These Styles need to define, among others settings for margins/min/max sizes, etc. needed to change the “compact” layout from 3b into final, user-friendly layout.

    Expression Blend

     

    Benefits

    This approach allows clear separation of responsibilities between different roles involved in the development: each role works on a different VS.NET project or source file, using tools specialized for the role. Each role can develop and focus on different skills and know-how: architetural and functional requirements, UI layout, code and appearance. Much of the work of each role can be done in parallel to the others.

    I am now experimenting with how best to use Command pattern in this approach. If this first attempt at blogging does not lead to my emotional ruin, I may write some more.

     


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker