Friday, December 17, 2010

WPF - Using Project Settings (Application / User Settings)

In this post, we will be discussing how we can use project properties in a WPF application. Specially, we will be considering how we can bind those properties to WPF elements.

Let us create a sample WPF application. We add a few settings to the project. In order to define settings, right click the startup project and select properties in Solution Explorer.


Now we define the settings. These settings might have different scopes. The available options are Application and User. An application properties is for all the user of the software. In case we updated a User setting, the update would just affect the current user.


It must be remembered that application wide settings are read-only. We can only change settings with user scope. In case we attempt to update the LabelText property defined above, it results in compile-time error.


Add a Window to the project. We add a few elements to the window as follows:

<Window x:Class="WpfApplication4.WindowBindingAppSettings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ProjectProperties="clr-namespace:WpfApplication4.Properties"
xmlns:local="clr-namespace:WpfApplication4"
Title="WPF Project Settings Binding" Height="368" Width="616">
<Grid>
<Label Height="28" HorizontalAlignment="Left"
Margin="16,30,0,0" Name="label1" VerticalAlignment="Top"
Width="132" >
<Label.Content>
<Binding Source="{x:Static ProjectProperties:Settings.Default}" Path="LabelText" />
</Label.Content>
</Label>
<TextBox Height="27" HorizontalAlignment="Left" Margin="154,30,0,0"
Name="textBox1" VerticalAlignment="Top" Width="288" />
<TextBox Height="27" HorizontalAlignment="Left" Margin="154,63,0,0"
Name="textBox2" VerticalAlignment="Top" Width="287" >
<TextBox.Text>
<Binding Source="{x:Static ProjectProperties:Settings.Default}" Path="ManagerText"
Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
</TextBox.Text>
</TextBox>
<Label Height="27" HorizontalAlignment="Left"
Margin="447,63,0,0" Name="label2" VerticalAlignment="Top" Width="114" >
<Label.Content>
<Binding Source="{x:Static ProjectProperties:Settings.Default}" Path="ManagerText" />
</Label.Content>
</Label>
<Button Content="Update" Height="25" HorizontalAlignment="Left"
Margin="154,96,0,0" Name="button1" VerticalAlignment="Top" Width="135"
Click="button1_Click" />
</Grid>
</Window>

As you can see we have bound the Application setting LabelText to a Label label1. We also have a text box textBox1. We are binding the text of this TextBox to the user setting ManagerText. We are setting mode as TwoWay and copying the value to the actual setting as the user keep changing the text in the TextBox it is bound to. In order to prove that the setting is actually being updated, we are binding the same setting to another TextBlock. You will notice that as we keep typing in the TextBox, the TextBlock keeps itself updating. As the application keeps running, the application would be using the same value of the properties. If we want to persist it, we should be saving it. You can see that the button1_Click handler takes care of saving the settings.

The code behine is as follows:

public partial class WindowBindingAppSettings : Window
{
public WindowBindingAppSettings()
{
InitializeComponent();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
Properties.Settings.Default.Save();
}
}

WPF based development environment generally have a policy of no code-behind. Since Default is singleton, you can save it from anywhere from the application (including View Model). Now run the application, the application appears as follows (except the green boxes I drew in order to show you the bindng.


You can notice that the Label text is correctly updated with LabelText property. Now start typing in the second TextBox, you should notice that the same values keep appearing in the adjacent TextBlock. If we click "Update" button, the same values would appear when the application runs next time.

It would be a little different if we are developing application in VB.net. Instead of Binding through Project Properties, we need to bind it directly through MySettings.

<Window x:Class="WpfApplication4.WindowBindingAppSettings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation";
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml";
xmlns:local="clr-namespace:WpfApplication1"
Title="WPF Project Settings Binding" Height="368" Width="616">
<Grid>
<Label Height="28" HorizontalAlignment="Left"
Margin="16,30,0,0" Name="label1" VerticalAlignment="Top"
Width="132" >
<Label.Content>
<Binding Source="{x:Static local:MySettings.Default}" Path="LabelText" />
</Label.Content>
</Label>
<TextBox Height="27" HorizontalAlignment="Left" Margin="154,30,0,0"
Name="textBox1" VerticalAlignment="Top" Width="288" />
<TextBox Height="27" HorizontalAlignment="Left" Margin="154,63,0,0"
Name="textBox2" VerticalAlignment="Top" Width="287" >
<TextBox.Text>
<Binding Source="{x:Static local:MySettings.Default}" Path="ManagerText"
Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
</TextBox.Text>
</TextBox>
<Label Height="27" HorizontalAlignment="Left"
Margin="447,63,0,0" Name="label2" VerticalAlignment="Top" Width="114" >
<Label.Content>
<Binding Source="{x:Static local:MySettings.Default}" Path="ManagerText" />
</Label.Content>
</Label>
<Button Content="Update" Height="25" HorizontalAlignment="Left"
Margin="154,96,0,0" Name="button1" VerticalAlignment="Top" Width="135"
Click="button1_Click" />
</Grid>
</Window>

The code behind in VB.net is as follows:

Public Class WindowBindingAppSettings
Private Sub button1_Click(ByVal sender As System.Object,
ByVal e As System.Windows.RoutedEventArgs)

MySettings.Default.Save()
End Sub
End Class

Settings from Other Project:
Generally a solution file contains many projects. It is possible that one project needs to access the settings from other project. In order to do that we need to set the Access Modifier of the settings as Public. It is available from top right when you open Project's properties in Visual Studio. Let's assume we need to access settings from other Project OtherProject. The name of property is SettingProperty.
 OtherProject.Properties.Settings.Default.SettingProperty = "Some value"

2 comments:

Erik said...

Great article. you really helped me out.

Anonymous said...

Hi, I'm just starting to play with the "user.config" and this helped me with setting the Access Modifier when using multiple projects, thanks.