Follow @PDSAInc October 2009 - Posts - Paul Sheriff's Blog for the Real World

Paul Sheriff's Blog for the Real World

This blog is to share my tips and tricks garnered over 25+ years in the IT industry

Paul's Favorites

October 2009 - Posts

Create a Login Screen in Silverlight 3

After my last blog post on “Create a Login Window in WPF”, I had a lot of requests for how to create the same login screen in Silverlight 3. There are actually just a few changes that had to be made to get the same look in feel in Silverlight 3. Figure 1 shows what this login screen looks like under Silverlight.

Silverlight 3 Login Screen
Figure 1: A Login Screen in Silverlight 3 (SLLogin.jpg)

Let’s take a look at how to create this screen in Silverlight.

Create a Silverlight Application

The first step is to create a Silverlight Application using VS.NET 2008. Once you have this created, open the MainPage.xaml that is created by the template. For this particular User Control you will set a specific width and height on the Grid control.

<Grid x:Name="LayoutRoot" Width="500" Height="200">
</Grid>

Next you will create some resources to help style the various elements you will be using on this Silverlight page. I have set some specific height properties on the controls for this page. I did this so the controls would not look stretched out. There might be a better way to do this, but I am still just learning Silverlight!

<Grid.Resources>
  <Style x:Key="tbStyle"
         TargetType="TextBlock">
    <Setter Property="Margin"
            Value="4"></Setter>
  </Style>
  <Style x:Key="textBoxStyle"
         TargetType="TextBox">
    <Setter Property="Margin"
            Value="4"></Setter>
    <Setter Property="MinWidth"
            Value="200"></Setter>
    <Setter Property="HorizontalAlignment"
            Value="Left"></Setter>
  </Style>
  <Style x:Key="passStyle"
         TargetType="PasswordBox">
    <Setter Property="Margin"
            Value="4"></Setter>
    <Setter Property="MinWidth"
            Value="200"></Setter>
    <Setter Property="HorizontalAlignment"
            Value="Left"></Setter>
  </Style>
  <Style x:Key="buttonStyle"
         TargetType="Button">
    <Setter Property="Margin"
            Value="6"></Setter>
    <Setter Property="Padding"
            Value="4"></Setter>
    <Setter Property="MinWidth"
            Value="50"></Setter>
  </Style>
</Grid.Resources>

The Border

Now that you have created the Grid size and the resources to be used within the Grid you now create the look for the outside border of the window. A Border control is used to form the outside of this login screen. You will set the CornerRadius attribute to “10” to give the nice rounded corners. You can set the BorderBrush to “Gray” and the BorderThickness to “3”. To achieve the shadow effect on this window, you will use the Border.Effect and the DropShadowEffect. Below is the xaml for the Border control.

<Border CornerRadius="10"
        BorderBrush="Gray"
        BorderThickness="3"
        Background="Beige"
        Padding="4">
  <Border.Effect>
    <DropShadowEffect Color="Gray"
                      Opacity=".50"
                      ShadowDepth="16" />
  </Border.Effect>

   ...
   ...

</Border>

Using a Grid Layout

To place each of the login screen elements within the border, a Grid control is used with specific column and row definitions. There are three columns in this login screen. The first column is for the image of the key, the second is for the labels and the third is for the TextBox, PasswordBox and Button controls.

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="60" />
    <ColumnDefinition Width="100" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

   ...
   ...

</Grid>

Placing the Key Image

The Key image that is in the upper left hand corner of this login screen is placed there by using a StackPanel control and an Image control. The StackPanel gives us just a little more control over the placement within the Grid. Notice the Grid.Column, Grid.Row and Grid.RowSpan attributes that are set on the StackPanel. The Grid.Row and Grid.Column specify in which row and column of the grid you wish to display the StackPanel. The Grid.RowSpan allows the key to float down over the next three rows of the Grid control. If you were to use a smaller or larger key image, then you would probably need to adjust this attribute accordingly. The Image control sets the source of its image to the Key.jpg file located in the Images folder. A drop shadow effect is applied to this image control just like you did with the Border control.

<StackPanel Grid.Column="0"
            Grid.Row="0"
            Grid.RowSpan="3">
  <Image Name="imgKey"
         Margin="8"
         Source="Images/Key.jpg">
    <Image.Effect>
      <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
    </Image.Effect>
  </Image>
</StackPanel>

The Large Title Label

The large label across the top of the login screen is simply a Label control with the appropriate Grid.Row, Grid.Column and Grid.ColumnSpan attributes set for placement. A FontSize of 18 is applied to make the text appear larger than the other labels on this screen. A Margin of 10 is used to give us some spacing from the border of the grid.

<Label Grid.Column="1"
       Grid.Row="0"
       Grid.ColumnSpan="2"
       FontSize="18"
       Margin="10"
       Text="Please Login To Access This Application" />

The Login Data Controls

The controls that gather the user name and password should be fairly familiar to you if you have been doing any Silverlight development. Each control is placed into a specific row and column of the Grid control. Instead of a Label control like you use in WPF, a TextBlock control is used in Silverlight.

<TextBlock Style="{StaticResource tbStyle}"
           Grid.Column="1"
           Grid.Row="0"
           Grid.ColumnSpan="2"
           FontSize="18"
           Margin="10"
           Text="Please Login To Access This Application" />
<TextBlock Style="{StaticResource tbStyle}"
           Grid.Column="1"
           Grid.Row="1"
           Text="User Name" />
<TextBox Style="{StaticResource textBoxStyle}"
         Grid.Column="2"
         Grid.Row="1"
         Name="txtUserName" />
<TextBlock Style="{StaticResource tbStyle}"
           Grid.Column="1"
           Grid.Row="2">Password</TextBlock>
<PasswordBox Style="{StaticResource passStyle}"
             Grid.Column="2"
             Grid.Row="2"
             Name="txtPassword" />

Notice the use of the Style attribute to apply the styles defined in the Grid.Resources section. In WPF you can apply global styles to a target control. In Silverlight you have to assign the style individually to each control.

The Buttons

The two buttons at the bottom of the screen are placed into the last row of the Grid control and into the second column of the grid by wrapping them into a StackPanel. The StackPanel has its HorizontalAlignment attribute set to Center and it’s Orientation attribute to Horizontal to allow the buttons to be centered within the StackPanel and to have the buttons appear side-by-side to each other.

<StackPanel Grid.Column="1"
            Grid.Row="3"
            Margin="10"
            HorizontalAlignment="Center"
            Orientation="Horizontal">
  <Button Style="{StaticResource buttonStyle}"
          Name="btnCancel"
          Content="Cancel">
    <Button.Effect>
      <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
    </Button.Effect>
  </Button>
  <Button Style="{StaticResource buttonStyle}"
          Name="btnLogin"
          Content="Login">
    <Button.Effect>
      <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
    </Button.Effect>
  </Button>
</StackPanel>

Summary

That is all there is to creating a nice looking login screen in Silverlight 3. Using the DropShadowEffect can add some spice to an otherwise flat-looking screen. I did not show any code for the login process as that will be dependent on your particular application. However, I hope this article gave you some ideas on how to layout screens in Silverlight 3.

NOTE: You can download the complete sample code at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "Silverlight 3 Login Screen" from the drop-down.

Good Luck With Your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

Create a Login Window in WPF

Most business applications require some sort of security system. You can always use Windows Authentication to authenticate a user, but sometimes you might want your own authentication scheme. When you do, you will need to create a login screen for your user to enter her login id and password. This article will explore creating a login window in WPF.

The UI for your login screen can contain any images and controls that you would like. In Figure 1 you can see a sample login screen that has an image of a key, a large title label across the top, two labels, a text box, a password box and two button controls. You can also make the border of the window rounded so that there is no close, minimize or maximize button and no title bar.

WPF Login Form 

Figure 1: A Login Screen

Of course this is just one version of a login screen but let’s take a look at how this is put together.

Creating the Window

To start, you need to create a window with no border and can be made into any shape you want. To do this you will set a few different attributes. The WindowStyle attribute normally allows you to set a single border, three-D border, or a Tool Window border. Setting this attribute to None will eliminate the border. The ShowInTaskbar attribute is optional, but if you are building a login screen you probably won’t want this window to show up in the Task Bar as it is going to be modal style form. The next two attributes, AllowsTransparency and Background work together. You must set AllowsTransparency to True to allow the Background to be set to Transparent. If you do not set these two attributes, then your border will still show up. Below is the xaml for this window.

<Window ...
   WindowStartupLocation="CenterScreen"
   AllowsTransparency="True"
   ShowInTaskBar=False
   Background="Transparent"
   WindowStyle="None"
   SizeToContent="WidthAndHeight"
   FocusManager.FocusedElement=
          "{Binding ElementName=txtUserName}">

   ...
   ...

</Window>

There are three additional attributes that are set on this window. The WindowStartupLocation attribute is set to “CenterScreen”  to ensure that the login screen is displayed in the middle of the screen when it is shown. You also set the SizeToContent attribute to WidthAndHeight to just take as much room for this window as the controls need that are contained within this window. The FocusManager.FocusedElement attribute is data-bound to the textbox control next to the User Name label. This tells WPF to place the cursor in this textbox once the screen is displayed.

The Border

Now that you have the Window xaml defined you now can create the look for the outside border of the window. A Border control is used to form the outside of this login screen. You will set the CornerRadius attribute to “10” to give the nice rounded corners. You can set the BorderBrush to “Gray” and the BorderThickness to “3”. You also want to give this border a nice wide Margin to allow room for the DropShadowEffect that we add to the outside of this border. If you do not do this, then the drop shadow will be chopped off. To achieve the shadow effect on this window, you will use the new Border.Effect and the DropShadowEffect that was added in WPF 3.5. This drop shadow effect is drawn using the Graphical Processing Unit (GPU) instead of being drawn using software. Thus drawing drop shadows is much more performant than in previous versions of WPF.

<Border CornerRadius="10"
        BorderBrush="Gray"
        BorderThickness="3"
        Background="Beige"
        Margin="24"
        Padding="4">
  <Border.Effect>
    <DropShadowEffect Color="Gray"
                      Opacity=".50"
                      ShadowDepth="16" />
  </Border.Effect>

   ...
   ...

</Border>

Using a Grid Layout

To place each of the login screen elements within the border, a Grid control is used with specific column and row definitions. There are three columns in this login screen. One for the image of the key, one for the labels and one for the TextBox, PasswordBox and Button controls.

<Grid>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="60" />
    <ColumnDefinition Width="100" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>

   ...
   ...

</Grid>

Placing the Key Image

The Key image that is in the upper left hand corner of this login screen is placed there by using a StackPanel control and an Image control. The StackPanel gives us just a little more control over the placement within the Grid. Notice the Grid.Column, Grid.Row and Grid.RowSpan attributes that are set on the StackPanel. The Grid.Row and Grid.Column specify in which row and column of the grid you wish to display the StackPanel. The Grid.RowSpan allows the key to float down over the next three rows of the Grid control. If you were to use a smaller or larger key image, then you would probably need to adjust this attribute accordingly. The Image control sets the source of its image to the Key.jpg file located in the /Images folder. A drop shadow effect is applied to this image control just like you did with the Border control.

<StackPanel Grid.Column="0"
            Grid.Row="0"
            Grid.RowSpan="3">
  <Image Name="imgKey"
         Margin="8"
         Source="/Images/Key.jpg">
    <Image.Effect>
      <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
    </Image.Effect>
  </Image>
</StackPanel>

The Large Title Label

The large label across the top of the login screen is simply a Label control with the appropriate Grid.Row, Grid.Column and Grid.ColumnSpan attributes set for placement. A FontSize of 18 is applied to make the text appear larger than the other labels on this screen. A Margin of 10 is used to give us some spacing from the border of the grid.

<Label Grid.Column="1"
       Grid.Row="0"
       Grid.ColumnSpan="2"
       FontSize="18"
       Margin="10">Please Login To Access This Application
</Label>

The Login Data Controls

The controls that gather the user name and password should be fairly familiar to you if you have been doing any WPF at all. Each control is placed into a specific row and column of the Grid control. Notice the use of the Tooltip attribute on the TextBox and the PasswordBox control. This gives the user an idea of what to put into each control if they hover their mouse over that control.

<Label Grid.Column="1"
       Grid.Row="1">User Name</Label>
<TextBox Grid.Column="2"
         Grid.Row="1"
         ToolTip="Enter Your User Name"
         Name="txtUserName" />
<Label Grid.Column="1"
       Grid.Row="2">Password</Label>
<PasswordBox Grid.Column="2"
             Grid.Row="2"
             ToolTip="Enter Your Password"
             Name="txtPassword" />

The Buttons

The two buttons at the bottom of the screen are placed into the last row of the Grid control and into the second column of the grid by wrapping them into a StackPanel. The StackPanel has its HorizontalAlignment attribute set to Center and it’s Orientation attribute to Horizontal to allow the buttons to be centered within the StackPanel and to have the buttons appear side-by-side to each other.

<StackPanel Grid.Column="2"
            Grid.Row="3"
            Margin="10"
            HorizontalAlignment="Center"
            Orientation="Horizontal">
  <Button Name="btnCancel"
          IsCancel="True"
          Content="Cancel"
          Click="btnCancel_Click">
    <Button.Effect>
      <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
    </Button.Effect>
  </Button>
  <Button Name="btnLogin"
          IsDefault="True"
          Content="Login"
          Click="btnLogin_Click">
    <Button.Effect>
      <DropShadowEffect Color="Gray"
                        Opacity=".50"
                        ShadowDepth="8" />
    </Button.Effect>
  </Button>
</StackPanel>

There are two special attributes that are set on these buttons. The IsCancel attribute is set to true on the Cancel button. Setting this attribute to true will fire the click event procedure on the Cancel button if the user presses the Escape key. The IsDefault attribute is set to true on the on the Login button. Setting this attribute to true will fire the click event procedure on the Login button if the user presses the Enter key.

Writing the Code for the Login Screen

In each of the click event procedures you will need to close the screen. In the Cancel click event procedure you will set the DialogResult property of the screen to a false value. This will inform the calling procedure that the user clicked on the Cancel button on this screen. In the Login click event procedure you will set the DialogResult property of the screen to a true value. This informs the calling procedure that the user clicked on the Login button and was authenticated. I am leaving it up to you to write the code for authenticating the user. Here is the code for the Cancel event procedure.

C#
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
  DialogResult = false;
  this.Close();
}

Visual Basic
Private Sub btnCancel_Click(ByVal sender As System.Object, _
 ByVal e As System.Windows.RoutedEventArgs)
  DialogResult = False
End Sub

And, here is the code for the Login event procedure.

C#
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
  // Write code here to authenticate user
  // If authenticated, then set DialogResult=true
  DialogResult = true;
}

Visual Basic
Private Sub btnLogin_Click(ByVal sender As System.Object, _
  ByVal e As System.Windows.RoutedEventArgs)
  DialogResult = True
End Sub

Displaying the Login Screen

At some point when your application launches, you will need to display your login screen modally. Below is the code that you would call to display the login form (named frmLogin in my sample application). This code is called from the main application form, and thus the owner of the login screen is set to “this”. You then call the ShowDialog method on the login screen to have this form displayed modally. After the user clicks on one of the two buttons you need to check to see what the DialogResult property was set to. The DialogResult property is a nullable type and thus you first need to check to see if the value has been set.

C#
private void DisplayLoginScreen()
{
  frmLogin frm = new frmLogin();

  frm.Owner = this;
  frm.ShowDialog();
  if (frm.DialogResult.HasValue && frm.DialogResult.Value)
    MessageBox.Show("User Logged In");
  else
    this.Close();
}

Visual Basic
Private Sub DisplayLoginScreen()
  Dim frm As New frmLogin()

  frm.Owner = Me
  frm.ShowDialog()
  If frm.DialogResult.HasValue And frm.DialogResult.Value Then
    MessageBox.Show("User Logged In")
  Else
    Me.Close()
  End If
End Sub

Summary

Creating a nice looking login screen is fairly simple to do in WPF. Using the DropShadowEffect can add a nice finished look to not only your form, but images and buttons as well. Using a border-less window is a great way to give a custom look to a login screen or splash screen. The DialogResult property on WPF Windows allows you to communicate back to the calling routine what happened on the modal screen. I hope this article gave you some ideas on how to create a login screen in WPF.

 

NOTE: You can download the complete sample code at my website. http://www.pdsa.com/downloads. Choose Tips & Tricks, then "WPF Login Screen" from the drop-down.


Good Luck With Your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

Posted: Oct 27 2009, 11:52 PM by psheriff | with 13 comment(s)
Filed under: ,
Binding to Config Settings in WPF

Almost every application has a configuration file used to store global settings. What would be cool is to have a global settings class that reads this data from the .Config file, then can be used to bind to UI elements within your WPF application. This is actually very easy to accomplish using the data-binding features in WPF.

Creating a Config Class

Below is a sample App.Config file you might add to a WPF application with a couple of settings in the <appSettings> element in the file.

<configuration>
  <appSettings>
    <add key="DefaultState" value="CA"/>
    <add key="IsActiveFlag" value="true"/>
  </appSettings>
</configuration>

These two values might be used as defaults to feed UI elements in your WPF application. So, you now need to create a class that will read these values from the .Config file. Below is a class named MySettings that has two properties; DefaultState and IsActiveFlag. In each of the Get methods is a call to the ConfigurationManager.AppSettings property to retrieve the appropriate element from the .Config file.

C#
public class MySettings
{
  public MySettings()
  {
  }

  public string DefaultState
  {
    get {
      return ConfigurationManager.AppSettings
              ["DefaultState"].ToString();
    }
  }

  public bool IsActiveFlag
  {
    get {
      return Convert.ToBoolean(ConfigurationManager.AppSettings
               ["IsActiveFlag"]);
    }
  }

  public void Refresh()
  {
    ConfigurationManager.RefreshSection("appSettings");
  }
}

Visual Basic
Public Class MySettings
  Public ReadOnly Property DefaultState() As String
    Get
      Return
        ConfigurationManager.AppSettings("DefaultState").ToString()
    End Get
  End Property

  Public ReadOnly Property IsActiveFlag() As Boolean
    Get
      Return Convert.ToBoolean( _
          ConfigurationManager.AppSettings("IsActiveFlag"))
    End Get
  End Property

  Public Sub Refresh()
    ConfigurationManager.RefreshSection("appSettings")
  End Sub
End Class

Now, you need to create an instance of this class in your WPF application and bind each property to a UI element.

Create Instance of Config Settings Class

Open your App.xaml or Application.xaml file and add a new namespace at the top that references your Namespace or application name. In my sample, I created a WPF application called WPFBindConfigSettings, so that is the name that I need to reference as shown in the code below.

<Application x:Class="WPFBindConfigSettings.App"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:src="clr-namespace:WPFBindConfigSettings"
 StartupUri="frmBindSettings.xaml">
  <Application.Resources>
    <ObjectDataProvider x:Key="odpSettings"
                        ObjectType="{x:Type src:MySettings}" />
  </Application.Resources>
</Application>

In the <Application.Resources> element you will add a <ObjectDataProvider> element that will create an instance of your MySettings class. As you can see in the above code that this is as simple as setting the ObjectType attribute in the ObjectDataProvider to src:MySettings. Set the  Key attribute for this ObjectDataProvider object to “odpSettings” as you will need to reference this resource from any window you create in your WPF application.

Bind to WPF UI

Now, let’s use this ObjectDataProvider to bind the values from the MySettings class to UI elements on a WPF Window as shown in Figure 1.

Binding to UI
Figure 1: You can bind settings from a Config

Below is the XAML to create the form shown in Figure 1.

<Grid>
  <StackPanel>
    <StackPanel Orientation="Horizontal">
      <Label>Default State</Label>
      <TextBox Name="txtDefaultState"
               Width="50"
               Text="{Binding Source={StaticResource odpSettings},
                      Path=DefaultState, Mode=OneWay}">
      </TextBox>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
      <Label>Is Active Flag?</Label>
      <CheckBox Name="chkIsActiveFlag"
                IsChecked="{Binding Source={StaticResource
                             odpSettings}, Path=IsActiveFlag,
                             Mode=OneWay}"
                VerticalAlignment="Center">
      </CheckBox>
    </StackPanel>
    <Button Name="btnRefresh"
            Click="btnRefresh_Click">Refresh</Button>
  </StackPanel>
</Grid>

In the above code you use the {Binding} syntax to read the values from the resource named “odpSettings” which is the Key value you created for the ObjectDataProvider in the App.xaml file. You must set the Mode=OneWay since the properties are read-only in the MySettings class. That is all there is to binding to the settings contained in the .Config file.

Refreshing the Config Settings

If you modify the values in the .Config file you will want to refresh the values in the ObjectDataProvider and ultimately in the UI. This can be easily accomplished with just a little bit of VB or C# code. Notice the Refresh method in the MySettings class presented above. The Refresh method in the MySettings class calls the ConfigurationManager.RefreshSection method to re-read a section in a .Config file. After refreshing the values from the .Config file you will want to have the UI be updated as well. You can accomplish this in a few different ways.

  1. Refresh each individual control (this approach takes the most code)
  2. Refresh the ObjectDataProvider which automatically refreshes the controls
  3. Implement the INotifyPropertyChanged interface. This is the best method to use

Let’s now take a look at each of these three approaches.

Refresh Each Individual Control

The first method is to refresh each individual control after calling the Refresh method on the MySettings class. This involves getting a reference to the MySettings instance in the ObjectDataProvider class. You can retrieve an instance of the ObjectDataProvider by calling the FindResource method on an instance of the current application. This is done in the source code shown in the following listing. Once you have the reference to the ObjectDataProvider you can grab an instance of the MySettings class and call the Refresh method on that object. This will cause the class to refresh the settings from the changed .Config file.

C#
private void RefreshControls()
{
  MySettings opts = (MySettings)((ObjectDataProvider)
      Application.Current.
          FindResource("odpSettings")).ObjectInstance;

  opts.Refresh();

  txtDefaultState.GetBindingExpression(
      TextBox.TextProperty).UpdateTarget();
  chkIsActiveFlag.GetBindingExpression(
      CheckBox.IsCheckedProperty).UpdateTarget();
}

Visual Basic
Private Sub RefreshControls()
  Dim opts As MySettings = DirectCast(DirectCast( _
        Application.Current.FindResource("odpSettings"), _
           ObjectDataProvider).ObjectInstance, MySettings)

  opts.Refresh()

  txtDefaultState.GetBindingExpression( _
     TextBox.TextProperty).UpdateTarget()
  chkIsActiveFlag.GetBindingExpression( _
     CheckBox.IsCheckedProperty).UpdateTarget()
End Sub

Next, you can update the target of the bindings of each control by using the GetBindingExpression method on the specific property on the control and then calling the UpdateTarget method on that property. This will force the control to refresh its binding.

Refresh the Data Provider

The second method you can use to refresh the data on the UI is to tell the ObjectDataProvider object to call its Refresh method. Again you need to get the instance of the ObjectDataProvider from the Application.Current property and call its FindResource method. You then get a reference to the MySettings object and call its Refresh method. Next, call the Refresh method on the ObjectDataProvider instance. This automatically refreshes all UI elements that are bound to this ObjectDataProvider.

C#
private void RefreshDataProvider()
{
  ObjectDataProvider dp =
  (ObjectDataProvider)Application.Current.
       FindResource("odpSettings");
  MySettings opts = (MySettings)dp.ObjectInstance;

  opts.Refresh();

  dp.Refresh();
}

Visual Basic
Private Sub RefreshDataProvider()
  Dim dp As ObjectDataProvider = _
    DirectCast(Application.Current.FindResource("odpSettings"), _
      ObjectDataProvider)
  Dim opts As MySettings = DirectCast(dp.ObjectInstance, _
      MySettings)

  opts.Refresh()

  dp.Refresh()
End Sub

Implement INotifyPropertyChanged

The third method you can use to refresh the data on the UI is to implement the INotifyPropertyChanged event on the MySettings class. When you implement this interface, you write code that will inform any data bindings that the property, or properties, on a class have changed.

You will modify the MySettings class in order to implement this interface. First off, you will need to import the System.ComponentModel namespace.

C#
using System.ComponentModel;

Visual Basic
Imports System.ComponentModel

Next, change the class definition to implement the interface.

C#
public class MySettings : INotifyPropertyChanged

Visual Basic
Public Class MySettings
  Implements INotifyPropertyChanged

Next you declare your intention to use the PropertyChangedEventHandler event procedure. To make it easier to call this from within the class, it is a good idea to create a method to raise this event. Below is code that needs to be added to the MySettings class.

C#
public event PropertyChangedEventHandler PropertyChanged;

protected void RaisePropertyChanged(string propertyName)
{
  var handler = PropertyChanged;
  if (handler != null)   {
    handler(this, new PropertyChangedEventArgs(propertyName));
  }
}       

Visual Basic
Public Event PropertyChanged(ByVal sender As Object, _
  ByVal e As System.ComponentModel.PropertyChangedEventArgs)  _
  Implements System.ComponentModel. _
               INotifyPropertyChanged.PropertyChanged

Protected Sub RaisePropertyChanged(ByVal propertyName As String)
  RaiseEvent PropertyChanged(Me, _
    New PropertyChangedEventArgs(propertyName))
End Sub

The code above takes care of notifying all bound objects about any changes to any properties in this class. Of course, it is up to you from within the class to call the RaisePropertyChanged method anytime you change the values from within the class. This means you need to change the Refresh method in the MySettings class to call the RaisePropertyChanged method.

C#
public void Refresh()
{
  ConfigurationManager.RefreshSection("appSettings");

  RaisePropertyChanged("DefaultState");
  RaisePropertyChanged("IsActiveFlag");
}

Visual Basic
Public Sub Refresh()
  ConfigurationManager.RefreshSection("appSettings")

  RaisePropertyChanged("DefaultState")
  RaisePropertyChanged("IsActiveFlag")
End Sub

The lines in bold are used to raise the PropertyChanged event so all bound objects to these properties are notified. Now you can call the following method in the Refresh button’s click event procedure in the WPF window.

C#
private void RefreshINotify()
{
  MySettings opts = (MySettings)((ObjectDataProvider)
   Application.Current.FindResource("odpSettings")).ObjectInstance;

  opts.Refresh();
}

Visual Basic
Private Sub RefreshINotify()
  Dim opts As MySettings = _
    DirectCast(DirectCast( _
      Application.Current.FindResource("odpSettings"), _
      ObjectDataProvider).ObjectInstance, MySettings)

  opts.Refresh()
End Sub

If you now run this sample and modify the .Config file and click the Refresh button, you will see the change made.

Summary

The data binding features of WPF are useful for more than just binding to database data. In this article you discovered how you can use the binding features to bind .Config file data to UI elements and how to refresh that data when the .Config file changes. You should use the INotifyPropertyChanged interface in most of the classes you create as this will make data binding to UI notifications almost automatic.

Download the Complete Sample

We have the completed sample for this article available on our website at http://www.pdsa.com/Downloads. Once there, select “Tips and Tricks” from the Category drop-down. Then select “WPF Sample – Bind Config Settings” from the Item drop-down.

Good Luck With Your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

Posted: Oct 19 2009, 10:49 PM by psheriff | with 1 comment(s)
Filed under: ,
Creating Border-less Windows in WPF

When creating a splash screen or to just have a different look for the windows in your WPF application, you might wish to eliminate the border to give it a custom look (see Figure 1). This can be done very easily with WPF.

No Border Image

Figure 1: A WPF window that has no border.

Setting Window Attributes

To get a border-less window, you need to set the following attributes on your Window.

  • WindowStyle="None"
  • ShowInTaskbar="False"
  • AllowsTransparency="True"
  • Background="Transparent"

The WindowStyle attribute normally allows you to set a single border, three-D border, or a Tool Window border. Setting this attribute to None will eliminate the border. The ShowInTaskbar attribute is optional, but if you are doing a splash screen you probably won’t want this window to show up in the Task Bar as it is only going to be there for a very short time. The next two attributes, AllowsTransparency and Background work together. You must set AllowsTransparency to True to allow the Background to be set to Transparent. If you do not set these two attributes, then your border will still show up.

The complete XAML code for the Window shown in Figure 1 looks like the following:

<Window x:Class="WPFExtras.frmWindowNoBorder"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  WindowStyle="None"
  ResizeMode="NoResize"
  ShowInTaskbar="False"
  AllowsTransparency="True"
  Background="Transparent"
  WindowStartupLocation="CenterScreen"
  Height="300"
  Width="300">
    <!-- Creates the shadow on the right and bottom -->
    <Border BorderBrush="Gray"           
            BorderThickness="0,0,2,2"
            CornerRadius="10"
            Background="Beige">
      <!-- Create space between shadow and the next border -->
      <Border BorderBrush="Transparent"
              BorderThickness="5"
              CornerRadius="10">
        <!-- The inner border -->
        <Border BorderBrush="Black"
                BorderThickness="1.5"
                CornerRadius="10">
          <StackPanel VerticalAlignment="Bottom" Margin="10">
            <Button Style="{StaticResource BasicControl}"
                    Click="Button_Click">Close Me</Button>
          </StackPanel>
        </Border>
      </Border>
    </Border>
</Window>

The XAML code for this Window uses 3 <Border> elements to create the shadow effect. The outer border is the shadow border that displays just on the right and the bottom. This is accomplished by setting the BorderThickness attribute to 0,0,2,2. The next border is to just give some space between the outer “shadow” border and the inner border. Notice the use of the CornerRadius attribute to give a nice rounded border effect.

Summary

Creating a border-less window is a very straight-forward process in WPF. Just by setting a few attributes will remove the border. Then you can create your own border by using the <Border> element. Or you could use any type of container you want to contain the controls on your Window.

Good Luck With Your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
Visit http://www.pdsa.com/Event/Blog for a free eBook on "Fundamentals of N-Tier".

Posted: Oct 12 2009, 10:24 AM by psheriff | with 11 comment(s)
Filed under: ,
More Posts