Last week I attended an InTrack session at Microsoft's Innovations Center in Barneveld, The Netherlands. On the agenda was .NET 3.5 with some basics about Windows Presentation Foundation (WPF), Windows Communication Foundation (WCF), Windows Workflow Foundation (used to be WWF, now WF due to the World Wide nature Fund) and LINQ; TLINQ (LinqToSql), PLINQ (Parallel Linq), XLINQ (LinqToXML), LinqToAmazon and LinqToFlickr.
About 18 months ago, I went to a meeting introducing WinFX (previous name for the above technologies and more), and was intrigued by WPF, the demo they showed there was a custom login screen, theming for each user in a nice and rich style. The most amazing part was the login for one of the kids, turning the entire app into a comic book style, including crooked textboxes, etc.
All this, and the fact that I have been waiting to play some more with Visual Studio 2008 (besides Linq) made me start making a WPF version of MSNPR.
I started out with a Grid, setting up a layout and creating a TextBox and a button, with a nice shape around it in the NKCSS house colors. While this is all nice, it has a lot of redundant code in the form of repeating markup in XAML.
<Window x:Class="MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="Window2" Height="300" Width="300">
<Grid>
<Grid.Background>#1F567D</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="65"/>
<RowDefinition Height="65"/>
</Grid.RowDefinitions>
<Border Style="{StaticResource NKCSSBorder}">
<Border.Name>USRBorder</Border.Name>
<Grid.Row>1</Grid.Row>
<Border.Child>
<TextBox Name="txtUSR" Style="{StaticResource NKCSSText}"></TextBox>
</Border.Child>
</Border>
<Button Style="{StaticResource NKCSSCopyButton}">
<Button.Name>btnCopyUSR</Button.Name>
<Button.ToolTip>Copy the username to the clipboard</Button.ToolTip>
<Grid.Row>1</Grid.Row>
<StackPanel Name="CopyUSRStack">
<Image Source="editcopy.png"></Image>
</StackPanel>
</Button>
<Border Style="{StaticResource NKCSSBorder}">
<Border.Name>PWDBorder</Border.Name>
<Grid.Row>2</Grid.Row>
<Border.Child>
<TextBox Name="txtPWD" Style="{StaticResource NKCSSText}"></TextBox>
</Border.Child>
</Border>
<Button Style="{StaticResource NKCSSCopyButton}">
<Button.Name>btnCopyPWD</Button.Name>
<Button.ToolTip>Copy the password to the clipboard</Button.ToolTip>
<Grid.Row>2</Grid.Row>
<StackPanel Name="CopyPWDStack">
<Image Source="editcopy.png"></Image>
</StackPanel>
</Button>
</Grid>
</Window>
I then added style elements in the Application.xaml
First attempt:
<Application x:Class="Application"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style x:Key="NKCSSBase" TargetType="{x:Type Control}">
<Setter Property="Control.BorderThickness" Value="2" />
<Setter Property="Control.BorderBrush" Value="#FFFFFF" />
<Setter Property="Control.Background" Value="#0A6EBA" />
<Setter Property="Control.Foreground" Value="White" />
</Style>
<Style x:Key="NKCSSPadded" TargetType="{x:Type Control}" BasedOn="{StaticResource NKCSSBase}">
<Setter Property="Control.Padding" Value="2" />
<Setter Property="Control.Margin" Value="10" />
</Style>
<Style x:Key="NKCSSBorder" TargetType="{x:Type Border}" BasedOn="{StaticResource NKCSSPadded}">
<Setter Property="Border.CornerRadius" Value="10" />
</Style>
<Style x:Key="NKCSSText" TargetType="{x:Type Control}" BasedOn="{StaticResource NKCSSPadded}">
<Setter Property="Control.Background" Value="#338AC9" />
<Setter Property="Control.Margin" Value="5,5,40,5" />
</Style>
<Style x:Key="NKCSSCopyButton" TargetType="{x:Type Button}" BasedOn="{StaticResource NKCSSPadded}">
<Setter Property="Button.Width" Value="30" />
<Setter Property="Button.HorizontalAlignment" Value="Right"/>
<Setter Property="Button.Margin" Value="0,18,18,18" />
<Setter Property="Button.Cursor" Value="Hand" />
</Style>
</Application.Resources>
</Application>
This resulted in error, even though the designer shows the correct output, only weird untraceable errors show up when running.
The error was:
Unable to cast object of type 'System.Windows.Controls.Border' to type 'System.Windows.Controls.TextBox'. Error at object 'System.Windows.Controls.Border' in markup file 'NKCSS MSN Password Recovery WPF;component/mainwindow.xaml'.
Even when rewriting it into the next block, errors show up when running the application. I guess styles aren't for me, back to redundant markup for the time being.
<Application x:Class="Application"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style x:Key="NKCSSBorder" TargetType="{x:Type Border}">
<Setter Property="Border.CornerRadius" Value="10" />
<Setter Property="Border.BorderThickness" Value="2" />
<Setter Property="Border.BorderBrush" Value="#FFFFFF" />
<Setter Property="Border.Background" Value="#0A6EBA" />
<Setter Property="Border.Padding" Value="2" />
<Setter Property="Border.Margin" Value="10" />
</Style>
<Style x:Key="NKCSSText" TargetType="{x:Type TextBox}">
<Setter Property="TextBox.Background" Value="#338AC9" />
<Setter Property="TextBox.Margin" Value="5,5,40,5" />
<Setter Property="TextBox.BorderThickness" Value="2" />
<Setter Property="TextBox.BorderBrush" Value="#FFFFFF" />
<Setter Property="TextBox.Foreground" Value="White" />
<Setter Property="TextBox.Padding" Value="2" />
</Style>
<Style x:Key="NKCSSCopyButton" TargetType="{x:Type Button}">
<Setter Property="Button.Width" Value="30" />
<Setter Property="Button.HorizontalAlignment" Value="Right"/>
<Setter Property="Button.Margin" Value="0,18,18,18" />
<Setter Property="Button.Cursor" Value="Hand" />
<Setter Property="Button.BorderThickness" Value="2" />
<Setter Property="Button.BorderBrush" Value="#FFFFFF" />
</Style>
</Application.Resources>
</Application>
After killing the whole style thing, and goinig back to the bare essentials, it still crashes when I try to debug it with the same error. For your amusement, here's the reworked code (without style):
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Grid.Background>#1F567D</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="65"/>
<RowDefinition Height="65"/>
</Grid.RowDefinitions>
<Border>
<Border.Name>USRBorder</Border.Name>
<Border.CornerRadius>10</Border.CornerRadius>
<Border.BorderThickness>2</Border.BorderThickness>
<Border.BorderBrush>#FFFFFF</Border.BorderBrush>
<Border.Background>#0A6EBA</Border.Background>
<Border.Padding>2</Border.Padding>
<Border.Margin>10</Border.Margin>
<Grid.Row>1</Grid.Row>
<TextBox Name="txtUSR">
<TextBox.Background>#338AC9</TextBox.Background>
<TextBox.Margin>5,5,40,5</TextBox.Margin>
<TextBox.BorderThickness>2</TextBox.BorderThickness>
<TextBox.BorderBrush>#FFFFFF</TextBox.BorderBrush>
<TextBox.Foreground>White</TextBox.Foreground>
<TextBox.Padding>2</TextBox.Padding>
</TextBox>
</Border>
<Button>
<Button.Name>btnCopyUSR</Button.Name>
<Button.ToolTip>Copy the username to the clipboard</Button.ToolTip>
<Button.Width>30</Button.Width>
<Button.HorizontalAlignment>Right</Button.HorizontalAlignment>
<Button.Margin>0,18,18,18</Button.Margin>
<Button.Cursor>Hand</Button.Cursor>
<Button.BorderThickness>2</Button.BorderThickness>
<Button.BorderBrush>#FFFFFF</Button.BorderBrush>
<Grid.Row>1</Grid.Row>
<StackPanel Name="CopyUSRStack">
<Image Source="editcopy.png"></Image>
</StackPanel>
</Button>
<Border>
<Border.Name>PWDBorder</Border.Name>
<Border.CornerRadius>10</Border.CornerRadius>
<Border.BorderThickness>2</Border.BorderThickness>
<Border.BorderBrush>#FFFFFF</Border.BorderBrush>
<Border.Background>#0A6EBA</Border.Background>
<Border.Padding>2</Border.Padding>
<Border.Margin>10</Border.Margin>
<Grid.Row>2</Grid.Row>
<TextBox Name="txtPWD">
<TextBox.Background>#338AC9</TextBox.Background>
<TextBox.Margin>5,5,40,5</TextBox.Margin>
<TextBox.BorderThickness>2</TextBox.BorderThickness>
<TextBox.BorderBrush>#FFFFFF</TextBox.BorderBrush>
<TextBox.Foreground>White</TextBox.Foreground>
<TextBox.Padding>2</TextBox.Padding>
</TextBox>
</Border>
<Button>
<Button.Name>btnCopyPWD</Button.Name>
<Button.ToolTip>Copy the password to the clipboard</Button.ToolTip>
<Button.Width>30</Button.Width>
<Button.HorizontalAlignment>Right</Button.HorizontalAlignment>
<Button.Margin>0,18,18,18</Button.Margin>
<Button.Cursor>Hand</Button.Cursor>
<Button.BorderThickness>2</Button.BorderThickness>
<Button.BorderBrush>#FFFFFF</Button.BorderBrush>
<Grid.Row>2</Grid.Row>
<StackPanel Name="CopyPWDStack">
<Image Source="editcopy.png"></Image>
</StackPanel>
</Button>
</Grid>
</Window>
Small update:
After posting on the MSDN forums about this problem, a helpful community member found the answer. It turns out that the root of the problem lies with the notation of the properties. For some reason, the WPF compiler seems to mess up when you specify the name of a WPF element in a child node, using the fully qualified namespace.
Example:
<Button>
<Button.Name>btnCopyPWD</Button.Name>
</Button>
If you were to write it in the following matter, it works without a problem:
Thank you jrboddie.
Working XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2" Height="300" Width="300">
<Grid>
<Grid.Background>#1F567D</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="65"/>
<RowDefinition Height="65"/>
</Grid.RowDefinitions>
<Border Name="USRBorder">
<Border.CornerRadius>10</Border.CornerRadius>
<Border.BorderThickness>2</Border.BorderThickness>
<Border.BorderBrush>#FFFFFF</Border.BorderBrush>
<Border.Background>#0A6EBA</Border.Background>
<Border.Padding>2</Border.Padding>
<Border.Margin>10</Border.Margin>
<Grid.Row>1</Grid.Row>
<TextBox Name="txtUSR">
<TextBox.Background>#338AC9</TextBox.Background>
<TextBox.Margin>5,5,40,5</TextBox.Margin>
<TextBox.BorderThickness>2</TextBox.BorderThickness>
<TextBox.BorderBrush>#FFFFFF</TextBox.BorderBrush>
<TextBox.Foreground>White</TextBox.Foreground>
<TextBox.Padding>2</TextBox.Padding>
</TextBox>
</Border>
<Button Name="btnCopyUSR">
<Button.ToolTip>Copy the username to the clipboard</Button.ToolTip>
<Button.Width>30</Button.Width>
<Button.HorizontalAlignment>Right</Button.HorizontalAlignment>
<Button.Margin>0,18,18,18</Button.Margin>
<Button.Cursor>Hand</Button.Cursor>
<Button.BorderThickness>2</Button.BorderThickness>
<Button.BorderBrush>#FFFFFF</Button.BorderBrush>
<Grid.Row>1</Grid.Row>
<StackPanel Name="CopyUSRStack">
<Image Source="editcopy.png"></Image>
</StackPanel>
</Button>
<Border Name="PWDBorder">
<Border.CornerRadius>10</Border.CornerRadius>
<Border.BorderThickness>2</Border.BorderThickness>
<Border.BorderBrush>#FFFFFF</Border.BorderBrush>
<Border.Background>#0A6EBA</Border.Background>
<Border.Padding>2</Border.Padding>
<Border.Margin>10</Border.Margin>
<Grid.Row>2</Grid.Row>
<TextBox Name="txtPWD">
<TextBox.Background>#338AC9</TextBox.Background>
<TextBox.Margin>5,5,40,5</TextBox.Margin>
<TextBox.BorderThickness>2</TextBox.BorderThickness>
<TextBox.BorderBrush>#FFFFFF</TextBox.BorderBrush>
<TextBox.Foreground>White</TextBox.Foreground>
<TextBox.Padding>2</TextBox.Padding>
</TextBox>
</Border>
<Button Name="btnCopyPWD">
<Button.ToolTip>Copy the password to the clipboard</Button.ToolTip>
<Button.Width>30</Button.Width>
<Button.HorizontalAlignment>Right</Button.HorizontalAlignment>
<Button.Margin>0,18,18,18</Button.Margin>
<Button.Cursor>Hand</Button.Cursor>
<Button.BorderThickness>2</Button.BorderThickness>
<Button.BorderBrush>#FFFFFF</Button.BorderBrush>
<Grid.Row>2</Grid.Row>
<StackPanel Name="CopyPWDStack">
<Image Source="editcopy.png"></Image>
</StackPanel>
</Button>
</Grid>
</Window>