WPF

WPF Validation Simplified

I have just written a new article at codeproject.com which is a simpler approach to labourous WPF Binding/Validation code. I have managed to create a nice re-usable control that makes the whole process a bit easier and clutters the XAML less.

I set out to develop a self binding/validating UserControl that would allow the user to specify the following:

  • The underlying bound object property to bind to
  • The position of the label
  • The label text
  • The update trigger to update the underlying data object property
  • The type of text that is allowed

It actually work out just fine, and it does all of the above. Further more I think its fairly easy to extend, which you could do. You can read (and even vote) for this article using the following url:

http://www.codeproject.com/KB/WPF/WPF_SelfValidatingTextBox.aspx 

Advertisements
Introduction

Another Threading Post Is Out (Part4)

As some of you may know I have embarked on a mission to write some articles over at codeproject about threading. Part 43 of this crusade is now available using this link. In this one I talk about ThreadPools. I hope you enjoy it.

CodeProject, WPF

Custom Tab Style

A little while ago I mentioned about how important I thought it was to create a brand, and I showed you that you can create some interesting looking controls by Templating/Styling the standard System.Windows controls to create a brand.

I also showed you a ScrollViewer and a Tab control which I had altered. I have since then decided there is no harm in sharing the TabControl code that I created.

So in this post we will discuss what you need to do to change a standard TabControl from

image

into the following slightly funkier TabControl

image

As one would expect its all about the Templates and Styles applied.

The first thing to understand is how the TabControl is made, its actually made of a Grid with 2 rows by default, which is something like this

rows

So we can alter this, by changing the RowDefinition to be ColumnDefinition, which will give us something like

cols

This is done with the following XAML

   1:  <Style x:Key="tab"  TargetType="{x:Type TabControl}">
   2:   <Setter Property="Template">
   3:     <Setter.Value>
   4:       <ControlTemplate TargetType="{x:Type TabControl}">
   5:         <Grid>
   6:           <Grid.ColumnDefinitions>
   7:             <ColumnDefinition Width="auto"/>
   8:             <ColumnDefinition Width="*"/>
   9:           </Grid.ColumnDefinitions>
  10:           <StackPanel Orientation="Vertical"
  11:              Background="{TemplateBinding Background}"
  12:              Grid.Column="0"
  13:              Panel.ZIndex="1"
  14:              IsItemsHost="True"/>
  15:           <Border
  16:              Grid.Column="1"
  17:              BorderBrush="Black"
  18:              BorderThickness="0"
  19:              Background="{TemplateBinding Background}"
  20:              CornerRadius="0">
  21:              <ContentPresenter
  22:                ContentSource="SelectedContent" />
  23:           </Border>
  24:         </Grid>
  25:       </ControlTemplate>
  26:     </Setter.Value>
  27:   </Setter>
  28:  </Style>

So that’s that part. The next thing to understand is that the TabItem. This is easily achieved by a little Style to replace the standard TabItem look and feel. This is what creates the individual TabItems with the arrows and disabled state.

   1:  <Style TargetType="{x:Type TabItem}">
   2:   <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
   3:   <Setter Property="Template">
   4:     <Setter.Value>
   5:       <ControlTemplate TargetType="{x:Type TabItem}">
   6:          <Grid>
   7:           <Border
   8:              Name="Border"
   9:              Margin="4"
  10:              BorderBrush="Transparent"
  11:              BorderThickness="0"
  12:              CornerRadius="0" >
  13:              <StackPanel Orientation="Horizontal">
  14:  
  15:              <Polygon x:Name="Arrow"
  16:                       HorizontalAlignment="Left"
  17:                       VerticalAlignment="Center" Margin="4"
  18:                       Width="14" Height="14"
  19:                       Fill="{TemplateBinding Foreground}"
  20:                       Visibility="Hidden">
  21:                  <Polygon.Points>
  22:                      <Point X="0" Y="0" />
  23:                      <Point X="0" Y="14" />
  24:                      <Point X="14" Y="7" />
  25:                  </Polygon.Points>
  26:              </Polygon>
  27:  
  28:              <!-- Header placeholder-->
  29:              <ContentPresenter x:Name="ContentSite"
  30:                    VerticalAlignment="Center"
  31:                    HorizontalAlignment="Left"
  32:                    ContentSource="Header"
  33:                    Margin="4"
  34:                    RecognizesAccessKey="True"/>
  35:              </StackPanel>
  36:            </Border>
  37:          </Grid>
  38:          <ControlTemplate.Triggers>
  39:              <Trigger Property="IsSelected"
  40:                       Value="True">
  41:                  <Setter Property="Panel.ZIndex"
  42:                          Value="100" />
  43:                  <Setter TargetName="Border"
  44:                          Property="Background"
  45:                          Value="Transparent" />
  46:                  <Setter TargetName="Arrow"
  47:                          Property="Visibility"
  48:                          Value="Visible" />
  49:              </Trigger>
  50:              <Trigger Property="IsEnabled"
  51:                       Value="False">
  52:                  <Setter TargetName="Arrow"
  53:                          Property="Fill"
  54:                          Value="{StaticResource Disabled}" />
  55:              </Trigger>
  56:          </ControlTemplate.Triggers>
  57:        </ControlTemplate>
  58:     </Setter.Value>
  59:   </Setter>
  60:  </Style>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }And lastly, we need to change the actual TabItem.Header DataTemplate to respect the disabled state. This is done as follows

   1:  <DataTemplate x:Key="tabHeader">
   2:      <Label x:Name="lbl" Margin="0" Content="{Binding}"
   3:         Foreground="{Binding RelativeSource={RelativeSource 
   4:         Mode=FindAncestor, AncestorType={x:Type TabItem},
   5:         AncestorLevel=1}, Path=Foreground}"
   6:         VerticalAlignment="Center" />
   7:      <DataTemplate.Triggers>
   8:          <Trigger Property="IsEnabled" Value="False">
   9:              <Setter TargetName="lbl"
  10:                      Property="Foreground"
  11:                      Value="{StaticResource Disabled}" />
  12:          </Trigger>
  13:      </DataTemplate.Triggers>
  14:  </DataTemplate>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }So that’s it, all we need to do now is apply these Styles/Templates to a TabControl like so

   1:  <TabControl Style="{StaticResource tab}"
   2:              Background="White" Foreground="Orange">
   3:      <TabItem Header="Item1 is here"
   4:               HeaderTemplate="{StaticResource tabHeader}"
   5:               Foreground="Orange" IsEnabled="False" >
   6:          <Button Content="Btn1" Margin="5"/>
   7:      </TabItem>
   8:      <TabItem Header="Item2"
   9:               HeaderTemplate="{StaticResource tabHeader}"
  10:               Foreground="Orange" >
  11:          <ScrollViewer >
  12:              <Canvas x:Name="canv" Width="1200" Height="1200">
  13:              </Canvas>
  14:          </ScrollViewer>
  15:      </TabItem>
  16:      <TabItem Header="Item3"
  17:               HeaderTemplate="{StaticResource tabHeader}"
  18:               Foreground="Orange" >
  19:          <Button Content="Btn3" Margin="5"/>
  20:      </TabItem>
  21:      <TabItem Header="Item4"
  22:               HeaderTemplate="{StaticResource tabHeader}"
  23:               Foreground="Orange" >
  24:          <Button Content="Btn4" Margin="5"/>
  25:      </TabItem>
  26:  </TabControl>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }And there you have it.

Here is a small demo project, should you wish to try it yourself.

Employment, WPF

Creating A Brand

I have just got a new job which involves creating a new application in WPF. I initially applied for this job, as it represented a challenge, which I quite like. At the interview stage, I was shown an existing WPF application that the existing team had created. There was nothing really that wrong with it, but it somehow just didn’t feel that WPF like.

They had the tools to do a good WPF app, for sure, they are bright people (otherwise I would not have wanted the job), but they were approaching it like a WinForms app, and it just felt, well WinForms like.

Now with all the new WPF arsenal that we have at our disposal, there is really no need that a WPF app needs to look like a WinForms app.

Using things like Animations we can do some really cool things, to set a WPF app apart, but taking a step back, I firmly believe what makes a world of difference is a common set of styled/templated controls. That are used throughout the application.

If you take the time to re-style the existing controls, you can create some quite cool looking controls that still work just the same as the original controls do, but they just look better.

I really think this 1 step, can contribute is such a major way to the way the whole app is perceived, it worth the time you spend customising the controls.

For example let’s consider a ScrollViewer control, whos default appearance looks like this:

 

ScrollViewer

And how about a TabControl, which by default looks like this:

tab 

Now I am no expert with Styling/Templating, but in 2 hours last night I was able to come up with some pretty satisfactory Styles/Templates for both of these controls. These new Styles/Templates, aid in branding of the overall app.

For me personally, each of the native control types that I end up using in the new WPF application, I will be attempting to create a new version of it, which sets the app apart, and gives it a touch of difference.

tabcntrol

In this figure there is a ScrollViewer contained within a TabItem (Item2). The overall TabControl has been altered to give the appearance you see here.

So by just spending a bit of time working with Styles/Templates you are able to create some pretty slick looking stuff. After all this screen shot is just a TabControl and a ScrollViewer, which looks nothing like the default control as shown below.

orig

 

I’m sure most of you will agree, the benefits from creating your own control styles, will surely help create a brand for your application. So got for it, don’t be shy, give it a try, like I say these 2 styles took me about 2 hours last night.

PS: I am unable to share the code for these 2 control Styles as I will be using them as part of a project. Sorry