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

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

DemoTwoOneDemoTwoTwoDemoTwoThree

Simple & Clean XAML

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

This looks simple and clean because it is.

<pt:Form x:Name="formMain" Style="{DynamicResource standardForm}" Grid.Row="1">

  <pt:FormHeader>
    <pt:FormHeader.Content>
      <StackPanel Orientation="Horizontal">
        <Image Source="User.png" Width="24" Height="24" Margin="0,0,11,0" />
        <TextBlock VerticalAlignment="Center" Text="General Information" FontSize="14" />
      </StackPanel>
    </pt:FormHeader.Content>
  </pt:FormHeader>

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

</pt:Form>

Background

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

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

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

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

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

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

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

Putting a Square Peg in Round Hole

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

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

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

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

Solutions

We need a solution that:

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

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

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

Second Choice – New Form Control

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

Form Control Solution Overview

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

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

Form Control

FormClass

Public Class Form
  Inherits ItemsControl

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

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

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

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

End Class

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

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

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

FormHeader

FormHeaderClass

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

FormItem

FormItemClass

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

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

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

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

</ResourceDictionary>
#Region "LabelHorizontalContentAlignment"

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

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

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

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

#End Region

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

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

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

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

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

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

Styling Form & FormItem

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

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

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

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

</Window.Resources>

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

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

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

Form Control Features

DemoOne

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

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

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

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

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

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

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

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

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

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

Downloads

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

Download Source 52KB

Close

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

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

Have a great day!

Just a grain of sand on the worlds beaches.

37 Responses to “WPF & Silverlight LOB Form Layout – Searching for a Better Solution”

  1. peteohanlon Says:

    Good stuff Karl, and I look forward to playing round with this in depth. The depth you’ve covered here puts my humble blog musings to shame, and is always worth reading. Keep on rocking.

  2. Karl Shifflett Says:

    Thanks Pete! Let’s continue to hoist the WPF banner nice and high!

    Cheers,

    k-dawg

  3. Josh Smith Says:

    Someone should build a monument somewhere, in your honor. This is GREAT!

    Josh

  4. Dew Drop - October 23, 2008 | Alvin Ashcraft's Morning Dew Says:

    [...] WPF & Silverlight LOB Form Layout – Searching for a Better Solution (Karl Shifflett) [...]

  5. wekempf Says:

    Great article. Related to Mr. Stovell’s blog post that we discussed on the Disciples mailing list. Like I said on there, I’m a HUGE fan of semantic markup with little or no direct layout/styling. It makes development SOOO much easier, ensures the application’s UI is consistent and provides the easiest route to skinning/themeing. What you have here looks like an excellent implementation of what I consider to be a pattern. The “Form” concept probably handles the 80% of the 80/20 rule, but a developer will need to know how to apply this pattern himself to address the other 20%. I think you did a fairly good job explaining the “how” here, so hopefully most developers can take this post and the provided code and figure out how to apply the pattern for their specific needs.

  6. Karl Shifflett Says:

    Josh – thank you!! See what your mentoring 12 months ago produced!

    Bill – we are in lock step on this. I know the WPF, LOB community can run with this.

    Cheers,

    Karl

  7. Peter Says:

    Very nice!

    I’m just learning WPF but it didn’t take long for me to get frustrated by the standard Grid approach to laying out forms. I tried to do something similar to your idea, inspired by the Form/FormItem containers in Flex. I’m a total newbie, but here are some of the things I did:

    1. My Form control extends HeaderedItemsControl, which saved me from having to create a separate FormHeader control … but I like how your FormHeader allows you to break your form into sections.
    2. Each FormItem is rendered in its own Grid with Grid.IsSharedSizeScope=True in the Form’s template … but your DockPanel approach gives more options for positioning labels.
    3. I didn’t do anything with attached properties (and probably wouldn’t know when/how to use them correctly). As a result, my forms look something like this:

    The attached properties definitely keep things lean.

    Anyhow, thanks for this and for the excellent PowerToys!

  8. colinblair Says:

    I am kind of feeling around in the dark right now in Silverlight control development so if any of this doesn’t make any sense I apologize in advance.

    I always liked the Extender idea that the AjaxControlToolkit uses. Is there some way to pull the label code out of the FormItem and put it in a seperate class. Something like Class FormControlLabelExtender : FormControlExtender.

    The Form and FormItem would then have a collection of FormControlExtender objects. I am thinking that you could within the XAML of the Form object put in the different extenders you want or add them directly to the individual items themselves as needed. I am also thinking that there should be a seperate class attached to the FormControlExtender to do the same job that IsItemItsOwnContainerOverride is doing for the FormItem at the per FormItemExtender level. This would be a seperate class (provider?) which can be changed by the programmer by inheriting the provider class and changing the instance attached to the FormControlExtender. That way you only have to write it once and share it between the existing Extenders. IsItemItsOwnContainerOverride itself would probably be moved into an instance of the new class so that the Form and FormItems all use the same object model.

  9. Karl Shifflett Says:

    Peter, thank you for your kind works and feedback, they are much appreciated.

    Colin, when I wrote this, my intention was to leverage as much exsisting WPF core features and code as possible. Since the ItemsControl exposed the functionality I needed, I used it.

    It took me much longer to write this blog post than to actually design, code, meet with Dr. WPF, code and create samples here.

    I’ll need to think about your direction. You wouldn’t have a concrete example would you?

    Cheers,

    Karl

  10. drwpf Says:

    Great work, as always, Karl! You are the master magician for the LOB dev community. :-)

    And I saw some nice shoutouts to your blog in ScottGu’s latest post (http://weblogs.asp.net/scottgu/archive/2008/10/22/october-22nd-links-asp-net-visual-studio-wpf-and-silverlight.aspx).

    Keep up the great work (which means, keep doing what you love)! Oh, and thanks for letting me have a small part in your brilliance. ;-) I look forward to the next time.

    Cheers,
    -dw

  11. Karl Shifflett Says:

    Dr. WPF,

    Thank you for your super kind encouragment. It was a real blessing working together. Looking forward to the next time also.

    Best to you always,

    Karl

  12. colinblair Says:

    As I feared, my previous comment didn’t make any sense. However, by taking apart your code for the last week and recomposing it several different ways I have really advanced my knowledge of WPF so thanks for that. From this starting point I now understand attached behaviors which negated what I was thinking in my original question.

  13. Nov 6th Links: ASP.NET, ASP.NET AJAX, jQuery, ASP.NET MVC, Silverlight and WPF - ScottGu's Blog Says:

    [...] WPF & Silverlight LOB Form Layout – Searching for a Better Solution: Karl Shifflett has another great WPF blog post that covers a cool way to perform flexible form layout for LOB scenarios. [...]

  14. BusinessRx Reading List : Nov 6th Links: ASP.NET, ASP.NET AJAX, jQuery, ASP.NET MVC, Silverlight and WPF Says:

    [...] WPF & Silverlight LOB Form Layout – Searching for a Better Solution: Karl Shifflett has another great WPF blog post that covers a cool way to perform flexible form layout for LOB scenarios. [...]

  15. XAML Power Toys « Carliños Blog Says:

    [...] Revisando un post del blog Karl on WPF me he encontrado con las XAML Power Toys, de momento no he tenido tiempo de [...]

  16. Link-Sammlung #3 Says:

    [...] WPF & Silverlight LOB Form Layout – Searching for a Better Solution: Karl Shifflet postete ein Weg um flexible Form-Layout für LOB Szenarien auszuführen. [...]

  17. asesta Says:

    Hi Karl,

    Great article. I was taking a slightly different approach to form layout but this is much nicer. Why doesn’t the FormItem generate the label when placed outside of the Form control? I understand the inherited properties would not work but why not the LabelContent?

    Al

  18. asesta Says:

    I actually found the answers to my questions.

    Thanks again for a great article.

    Al

  19. Karl Shifflett Says:

    Asesta,

    Glad you sorted it out. Have a great day!

    Karl

  20. bbakermai Says:

    As far as I can tell, you can’t use DefaultStyleKeyProperty.OverrideMetadata or FrameworkPropertyMetadata for a Silverlight Class Library version of the XAMLPowerToys.Controls. Here’s a blog post that might help: http://tinyurl.com/6nodxp

  21. toso06 Says:

    Hi Karl!

    After TechEd Barcelona 2008 and seeing that MS have started to use WPF themselves we plan to start using WPF for new internal LOB applications. XAML Power Toys support for the Form control would really help.

  22. Karl Shifflett Says:

    bbakermai: I’ve come up with a better solution than this form. I’ll post it soon. It will work in both Silverlight and WPF.

    toso06: I’ll add support for the new solution in XAML Power Toys.

    Thank you both for your great feedback.

    Cheers,

    Karl

  23. mickan98 Says:

    Karl, good stuff, here’s some feedback from an LOB developer (well, manager really) as requested:

    Think about “level of indirection” as the complexity builds up. These form patterns are (necessarily) much more complex (or at least, more layered) than newcomers might think.. don’t give up! Each “section” of a “real” form would have some presentation like your examples. This would be contained within other layout (such as a header section, then multiple tabbed sections below. Each tab content would look like your example). There is opportunity for taking your approach not only for the field layout, but also providing patterns for the layout of the form too.

    Not only form designers, but also “customisers” at the deployment site (for ISV pducts) would like to apply this kind of styling/customization for local mods. This adds another layer as to when and how the form is constructed. One “level of indirection” is that the list of fields to be displayed can be saved as a list, then run time binding can pick out those fields that this user wants to see. (Or, the list might be generated – on a server, say – with security or role customization in mind, then applied on the client). Exposing PowerToy like functionality for local screen modification would be really cool.

    Designers might like to pick from a pallette of layouts and styles somewhat like Office07 tables.

    The icing on the cake is building this into a MVP or M-V-VM type architecture. Then screen designers (including Blend) can rock at the V-VM (or V-P) intermediary, and the rest of the business logic and error handling continues to work unimpeded.

    Lastly, condier how a metadata-like provider serving up information regarding the business objects and their fields can provide information at run time and screen genration time.

    The hardest part of the up front design is to make sure the implmentation layers dont overlap. Doing too much to quickly can cause this to happen. Take it step by step. Think hard about separation of concerns at each layer, and limiting the responsibilities of each.

    Good luck!

  24. jarrettmeyer Says:

    Karl,

    I love your posts! Your work and enthusiasm really saves me a lot of time. Not to be overanxious, but any idea when the SL version will be available?

    Thanks,
    JM

  25. Karl Shifflett Says:

    JM,

    Thank you for your kind remarks.

    I’ll be looking at Silverlight with vigor after MIX09.

    Cheers,

    Karl

  26. Nov 6th Links: ASP.NET, ASP.NET AJAX, jQuery, ASP.NET MVC, Silverlight and WPF | designersmantra.com Says:

    [...] WPF & Silverlight LOB Form Layout – Searching for a Better Solution: Karl Shifflett has another great WPF blog post that covers a cool way to perform flexible form layout for LOB scenarios. [...]

  27. Valeriu Caraulean Says:

    Thanks, it’s a very interesting idea. With one small remark – it’s implemented in VB :)

    I’ve converted that to C# (nothing religiuos, I preffer to keep our solution homogeneous) but I’ve hit a very strange problem: when included in our “Infrastructure” project and referencing it from other project within same solution, on some PCs the content of Form is not visible, nor in design nor in runtime. On one dev station it works like a charm, in others – no way, empty screens. Same code, same solution. We’ve tried to find differences in installed frameworks and patches, but nothing found. Only one workarround found: when compiled in a separate assembly and referenced that – worked well everywhere… !?

    Do you have any clue what can cause this strange behavior? Any directions to check?

    PS: You’ve mentioned in a comment to this post that you have a even better solution that the Form. Have you shared it somewhere?

    Thanks

  28. Karl Shifflett Says:

    Valerui,

    Try taking the executable from this post and running it on the machines with the issue. This could help validate the code here and the client setup on those machines.

    Do the target machines have .NET 3.5 SP1?

    I have not yet released the “better” solution because I took it to work and if I release it here, I may have issues. If I don’t get the new solution approved at work, I’ll release it here.

    Cheers,

    Karl

  29. Nov 6th Links: ASP.NET, ASP.NET AJAX, jQuery, ASP.NET MVC, Silverlight and WPF | rapid-DEV.net Says:

    [...] WPF & Silverlight LOB Form Layout – Searching for a Better Solution: Karl Shifflett has another great WPF blog post that covers a cool way to perform flexible form layout for LOB scenarios. [...]

  30. clupprich Says:

    Hi Karl,

    I have some problems with the xaml part of your library. VS complains about the Triggers in the resource dictionary for the FormItem component (”Cannot set the Template Property LabelPosition”) and the Setters in the dictionary for the Form (same error message). Any hints?

    Best regards,
    Christoph

    • Karl Shifflett Says:

      Christoph,

      I have not had anyone say the supplied project didn’t work for them, sorry you have having a problem.

      Are you using the code supplied in the download, or have you moved it to another project?

      What version of Visual Studio are you using? Any service packs applied?

      Cheers,

      Karl

  31. clupprich Says:

    Karl,

    I’ve translated the code to C# because I don’t have VB installed. I’m using VS2008 with SP1 and the Silverlight Tools, running on .NET 3.5 SP1.

    Thanks for your help,
    Christoph

  32. narayans Says:

    Hi Karl,
    Great post and thank you for showing what you can do with ControlTemplates.

    I am working on a project where this would be very useful however, I was unable to get your code to work in Silverlight. In addition to the issue with OverrideMetadata not being available, there are other subtle issues (like Triggers not available in SL3 etc). After spending a few hours on this I was unable to get it to work and that’s just because of my current lack of understanding of templated controls (soon to be remedied =).

    If you do manage to port the Form to SL3, that would be very much appreciated. Alternatively, if I do manage to get it working, I’ll email you the code and post it on my blog.

    Narayan

    • Karl Shifflett Says:

      Narayan,

      Yes, SL has less features than WPF. However, you can “normally” accomplish the task in other ways.

      I have not tried porting this code to SL yet. I’m snow under for a few weeks launching Ocean 2.0 and the BBQ Shack. When I get that done, I’ll have a look at this.

      Cheers,

      Karl

Leave a Reply

You must be logged in to post a comment.