De WPF Integratio (About WPF Integration)

.NET, Blend, Silverlight, Technical stuff, Work, WPF
See comments

Introduction

I’ve been posting a lot about Silverlight lately, but hey, here is a WPF post, and about WPF integration, no less.
Note: To fully understand this article, you should have a basic understanding of WPF, styles and templates, triggers, etc…

In my current project at work, I act as WPF Integrator. I am that dude who sits between the designers and the developers, and tries to avoid that they fight too much. Or something. Sometimes it works, sometimes it doesn’t, you know how it is with kids. They need their freedom. But I digress.

One important task of a WPF Integrator is (drum roll) WPF integration. For us, this operation usually occurs when we have a design iteration. The way we create application components is (roughly) the following:

  • The Developer creates the component in Visual Studio. The component is composed of a main assembly (EXE or DLL), containing “functional XAML” and source code (code-behind), and a “Skins” DLL containing XAML resource dictionaries.
    (Note: Because we don’t want any source code into the “Skins” DLL, and to avoid circular references, we actually have a 3rd assembly called “Converters”. As the name shows, this assembly contains the converters (and other helper classes) that are referenced from the Skins DLL).
  • Together with the WPF Integrator, they create a “raw” UI. That means a basic layout made of “functional XAML”, according to the wireframes created by our user experience engineers.
    (Note: “functional XAML” is the XAML code that is not strictly doing look&feel. For example, a Button tag is functional XAML, while the style and template it uses are “design XAML”).
  • The WPF Integrator prepares the Skins DLL by exporting all styles to it (using Blend). We follow certain guidelines in naming all the components (styles, templates, DLL names, etc…) and also in the structure of the styles and templates (see below).
  • The Developers start what they do best, Developing. Meanwhile, the Designer do what they do best (let me hear you:) Designing! This is the Design iteration I was referring to before.
    (Note: The Developer *only* works in the main assembly. The Designer *only* works in the Skins assembly.
  • If the Designer needs to change something in the main assembly, they contact the WPF Integrator to coordinate.
  • Similarly, if the Developer needs to change something in the Skins DLL, they contact the WPF Integrator to coordinate.
  • When a set of features are complete, the Developers’ and Designers’ work is integrated and tested.

Typically, we integrate the design to the application during design workshops, where a couple of Designers and Developers (and the WPF Integrator) sit together and work together, pretty much in an Extreme Programming spirit. These workshops are very intense and interesting, and usually allow fast progress in the application’s look&feel.

Conventions, file structure, naming

  • A control refers to a Style which in turn refers to a Template (this is to facilitate the designers’ job in Blend).
  • A control does *not* set its template directly, but always through a style.
  • If triggers are needed in the main assembly, the local style refers to a “BasedOn” style located in the Skins DLL.
  • A Style key is named like the control it refers to, suffixed with “Style”. For example “MySpecificButtonStyle” or “ListBoxStyle” (for all ListBoxes), etc…
  • A Template key is named like the control it refers to, suffixed with “Template”. For example “MySpecificButtonTemplate” or “ListBoxTemplate” (for all ListBoxes), etc…
    (note: We use the “Template” suffix for ControlTemplate and DataTemplate).
  • The skin resources for a given control are stored in a resource dictionary file with the “Skin” suffix. For example, the control “MyUserControl”‘s resource dictionary is named “MyUserControlSkin.xaml”.

These guidelines help the designers to understand which Style and Template belong to which control. Note that Blend makes that task easier by allowing to navigate from the main assembly to the Skins assembly with a succession of clicks.

Typical Designer workflow

The very first task a designer must do when he gets the code is to understand its structure. This is where the conventions mentioned above help. Typically, they work this way:
(Note: You can download a sample application here, open the SLN file in Blend, and then open the main window (Window1.xaml))

  • Open the application’s main window in Blend and check the logical tree.
  • If a user control is found, right-click on it and choose “Edit control” (fig 1). This opens the User Control XAML file in Blend.
    (Of course, this fails if the User Control’s source code is not available).
  • For any control they want to skin, select the control, and then choose the menu “Object / Style” (fig 2 and 3).
  • At this point, the style chosen can be local (for example if the Developer need to use a Trigger, etc. See listing 1). The Designers are trained to check the name of the file in which they are currently located (in Blend). If the file is named without a “Skin” suffix (for example MyPlugIn.xaml), they may not edit it. In that case, they look for a BasedOn style (fig 4). If they are currently located in a file with a “Skin” suffic (for example “MyPlugInSkin.xaml”, then they may edit it (fig 5).
  • Once in the Style, they can select the context menu “Edit Control Parts (Template) / Edit Template”. This opens the Control Template in Blend, where they can rework to look&feel of the control completely (including triggers, animations, etc…)
Figure 1: Edit control
Figure 1: Edit control
 
Figure 2: Selecting a control
Figure 2: Selecting a control
 
Figure 3: Edit style
Figure 3: Edit style
 
<Button Content="GO"
        Grid.Column="1"
        Click="GoButton_Click">
   <Button.Style>
     <Style TargetType="Button"
            BasedOn="{StaticResource RoundButtonStyle}">
       <Setter Property="IsEnabled"
               Value="True" />
       <Style.Triggers>
         <DataTrigger Binding="{Binding ElementName=DirectoryNameTextBox,
                                        Path=Text}"
                      Value="{x:Static sys:String.Empty}">
           <Setter Property="IsEnabled"
                   Value="False" />
         </DataTrigger>
       </Style.Triggers>
     </Style>
   </Button.Style>
 </Button> 
 
Listing 1: Local style using a Trigger, Based On a skin style
 
Figure 4: Edit
Figure 4: Edit “based-on” style
 
Figure 5: Editing the style in the Skin file
Figure 5: Editing the style in the Skin file

Note: Here we see the advantage of setting the “Template” property in the Style instead of directly in the control: The Designer can see the “shape” of the control already in Blend, without having to rebuild.

Figure 6: Editing the template in the Skin file
Figure 6: Editing the template in the Skin file
 

The importance of Blend

This workflow would fail miserably without Blend. It can never be repeated often enough: You should keep your application Blendable! (as long as possible). Blend will fail to represent the UI in some circumstances. For example, if your application connects to a COM based component, this is something that Blend cannot handle. Similarly, if your application uses any kind of network service to get data, Blend won’t be able to represent this data. This is where the MVVM (Model – View – ViewModel pattern comes handy: By enforcing a data-driven UI, you give the developer the possibility to create “design-time” data, i.e. data which is only used when the application runs in Blend (or in the Visual Studio WPF designer). I could talk about that for hours, and this jumps the scope of this post, but you can read more info about MVVM here:

Using WinMerge as an integration tool

During these integration phases, I use WinMerge a lot. The reasons for using this merging tool are multiple:

  • It is probably the best merging tool currently available for Windows (if someone disagrees, don’t hesitate to comment below!!).
  • Our Designers don’t work in our source control infrastructure. They get a copy of the code, refactored as a standalone application. This allows them to test the application easily without having to install a whole networking system (our application is following a Service Oriented Architecture). The aplication they get features a test mode, allowing them to simulate certain conditions (again, see my TechDays talk and the source code for details). Because they work disconnected from the source control, a merging operation is needed.
  • The merging steps give me a good occasion to review the Designers and Developers work, and to understand it. This is an additional step towards code consistency and code quality (4 eyes review principle).

WinMerge is simply amazing, a must-use tool for a WPF Integrator (at least if you work according to a similar workflow as we do). It is free (amazing, when you see the quality of this tool), was clearly developed by people who needed such a tool and decided to create it (according to the “eat your dog food” idea), and can even be integrated into your favourite source control framework (yes, even ClearCase, which we are forced to use). You can compare folders, binary files, text files with a very clear user interface. All merging operations can be performed using the keyboard only, which is extremely ergonomic. Honestly, I love that tool.

By the way, I didn’t mention it yet, but you can also edit both files you are comparing in WinMerge, and save both of them.

WinMerge, merging tool
WinMerge, merging tool
 
 

Conclusion

Much has been written about the Designer-Developer workflow, the WPF Integrator role, the MVVM (or MV*) pattern, etc… In our project, we have the chance to use these principles in a real life situation. I can honestly say, I rarely had so much fun developing software ever. The only thing I can think of that made (almost) as much fun was the big ASP.NET project I worked on prior to this one. The Integrator role is a great place to be.

(Note: I also file this under Silverlight because WinMerge is also very useful for Silverlight integration, even though the Style and Template system is not as rich as in WPF yet).

Previous entry | Next blog entry

Comments for De WPF Integratio (About WPF Integration)