Still looking for a sponsor Max Paulousky is looking for a Silverlight/.Net job in the Commonwealth

Share to Facebook Tweet this! Share to MySpace Share to Google Share to Live   Share via AddThis

GroupBox Sketching Control for WPF applications Using Blend

Microsoft Expression Blend 3 has a great feature – SketchFlow. It allows creating gorgeous prototypes for Silverlight and WPF applications. But it has some disadvantages like shortage of controls. For example, there are no sketching GroupBox controls in Silverlight and WPF sets, sketching DataGrid (Silverlight and WPF) etc. So, I am going to create a sketching GroupBox control WPF.

Every WPF Sketch Screens application has got the SketchStyles.xaml file. This file contains styles for all sketching controls. I am going to add a new style here. Initially, I create a stub for the GroupBox control there:

<Style x:Key="GroupBox-Sketch" TargetType="{x:Type GroupBox}">
....
</Style>

where x:Key=”GroupBox-Sketch” is the name of the control that will be displayed in the list of ones.

Then I should add a markup for internal elements of the GroupBox. I use a grid with four columns and rows:

<Grid SnapsToDevicePixels="True">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="6"/>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="6"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="Auto"/>
    <RowDefinition Height="*"/>
    <RowDefinition Height="6"/>
  </Grid.RowDefinitions>
</Grid>

Next step is adding a rectangle for the GroupBox.

Initial markup for the WPF GroupBox sketching control It is placed in grid row 1 (Rowspan = 3); column 0 (ColumnSpan = 4).

<SketchControls:SketchRectangleUC x:Name="Rectangle" Background="{TemplateBinding Background}" 
  BorderBrush="{DynamicResource BaseBorder-Sketch}" Radius="0" ExtensionLength="0" 
  ExtensionVariance="0" SegmentLength="8" SegmentVariance="0.1" SegmentOffset="0.12" 
  FocusVisualStyle="{DynamicResource FocusControl-Sketch}" HorizontalAlignment="Stretch" 
  VerticalAlignment="Stretch" BorderThickness="0,0,0,0" Grid.ColumnSpan="4" Grid.Row="1" 
  Grid.RowSpan="3" />

After sketching rectangle, I would like to add a header label. There are some requirements to it. It should be able to allow changing font, font size and the GroupBox control should be changed appropriately.

The header is a combination of a ContentPresenter and a Border elements. First one should be placed inside last one. The Content property of the ContentPresenter is binded to the Header property of the GroupBox control, so users will be able to change header’s text at design-time.

<Border Background="Transparent" Panel.ZIndex="2" x:Name="Header"  Grid.Column="1" 
  Grid.Row="0" Grid.RowSpan="2" >
  
  <ContentPresenter TextElement.Foreground="{StaticResource BaseBorder-Sketch}" 
  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
  Content="{TemplateBinding Header}" ContentSource="Header" 
  ContentStringFormat="{TemplateBinding HeaderStringFormat}" 
  ContentTemplate="{TemplateBinding HeaderTemplate}" RecognizesAccessKey="True" 
  HorizontalAlignment="Center" x:Name="HeaderPresenter" />
</Border>

After described changes, I should add two lines below the Header block and above sketching rectangle to create a gap for header area. The most important requirement is these line should be able to change their width according to the width of the header. I need two lines because thickness of sketching rectangle is a bit more than thickness of a line

<Line Grid.Column="1" Grid.Row="1" Stroke="{TemplateBinding Background}" 
  X1="0" Y1="2" X2="{Binding ElementName=HeaderPresenter, Path=ActualWidth}" 
  Y2="2" Panel.ZIndex="1" StrokeThickness="{Binding ElementName=Rectangle, 
  Path=StrokeWidth}"/>        
<Line Grid.Column="1" Grid.Row="1" Stroke="{TemplateBinding Background}" 
  X1="0" Y1="1" X2="{Binding ElementName=HeaderPresenter, Path=ActualWidth}" 
  Y2="1" Panel.ZIndex="1" StrokeThickness="{Binding ElementName=Rectangle, 
  Path=StrokeWidth}"/>    

And last but not least, I need an area for content that will be put into the GroupBox.

<ContentPresenter Margin="{TemplateBinding Padding}" 
  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
  Grid.Column="1" Content="{TemplateBinding Content}" 
  ContentTemplate="{TemplateBinding ContentTemplate}" 
  Grid.ColumnSpan="2" Grid.Row="2" Panel.ZIndex="1" />

That is it!

How the control looks in an application:

Example of the WPF GroupBox sketching control

Here is the full code of the GroupBox-Sketching control. This code works only for WPF projects, not Silverlight.

<Style x:Key="GroupBox-Sketch" TargetType="{x:Type GroupBox}">
  <Setter Property="BorderBrush" Value="{StaticResource BaseBorder-Sketch}"/>
  <Setter Property="Background" Value="{StaticResource BaseBackground-Sketch}"/>
  <Setter Property="FontFamily" Value="{StaticResource FontFamily-Sketch}"/>
  <Setter Property="Foreground" Value="{StaticResource BaseBorder-Sketch}"/>
  <Setter Property="FontSize" Value="{StaticResource SizeDouble-Sketch}"/>
  <Setter Property="FontWeight" Value="{StaticResource FontWeight-Sketch}"/>                    
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type GroupBox}">
        <Grid SnapsToDevicePixels="True">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="6"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="6"/>
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="6"/>
          </Grid.RowDefinitions>
  
          <Border Background="Transparent" Panel.ZIndex="2" x:Name="Header"  Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" >
            <ContentPresenter TextElement.Foreground="{StaticResource BaseBorder-Sketch}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Header}" ContentSource="Header" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentTemplate="{TemplateBinding HeaderTemplate}" RecognizesAccessKey="True" HorizontalAlignment="Center" x:Name="HeaderPresenter" />
          </Border>
  
          <SketchControls:SketchRectangleUC x:Name="Rectangle" Background="{TemplateBinding Background}" BorderBrush="{DynamicResource BaseBorder-Sketch}" Radius="0" ExtensionLength="0" ExtensionVariance="0" SegmentLength="8" SegmentVariance="0.1" SegmentOffset="0.12" FocusVisualStyle="{DynamicResource FocusControl-Sketch}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="0,0,0,0" Grid.ColumnSpan="4" Grid.Row="1" Grid.RowSpan="3" />
  
          <Line Grid.Column="1" Grid.Row="1" Stroke="{TemplateBinding Background}" X1="0" Y1="2" X2="{Binding ElementName=HeaderPresenter, Path=ActualWidth}" Y2="2" Panel.ZIndex="1"   StrokeThickness="{Binding ElementName=Rectangle, Path=StrokeWidth}"/>        
          <Line Grid.Column="1" Grid.Row="1" Stroke="{TemplateBinding Background}" X1="0" Y1="1" X2="{Binding ElementName=HeaderPresenter, Path=ActualWidth}" Y2="1" Panel.ZIndex="1" StrokeThickness="{Binding ElementName=Rectangle, Path=StrokeWidth}"/>    
      
          <ContentPresenter Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Grid.Column="1" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Grid.ColumnSpan="2" Grid.Row="2" Panel.ZIndex="1" />
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Unfortunately, Silverlight does not have own GroupBox control. This means, we have to use 3rd party GroupBox controls to create sketching ones. Here is an example how to create one. But there is a negative moment in that implementation – this control does not look well when user changes font size of a header area.

This work is licensed under a Creative Commons Attribution By license.
Comments have been closed on this topic.