Page 1 of 1

[WPF] Two-way Binding To A Static Property How to bind a control in a WPF project to a static property in a class

#1 Core  Icon User is offline

  • using System.Linq;
  • member icon

Reputation: 774
  • View blog
  • Posts: 5,097
  • Joined: 08-December 08

Posted 27 August 2009 - 04:31 PM

In this tutorial I will explain how to bind a control to a static property. As you probably know, one-way binding to a static property is not a big problem. A simple line of code like this will bind a control property to another property in any class:

{x:Static Namespace:Class.Property}"



Nothing really complicated to this point. But this shows how to implement the one-way binding. The problem arises when it comes to two-way binding. Let’s first see, how one-way binding is different from the two-way one.

When you use one-way binding to a property, basically, you can only get the value of the property without the possibility of modifying it. This is useful when you have a property that has a constant value (for example, an access key or Boolean flag) and you only need to check it or assign it to some other control property.

From the other side, the two-way binding allows you to modify the property depending on the state of the control property, that was assigned as the binding element. Therefore, for example, you have a CheckBox control in your window. This CheckBox has two states – it is either checked (True) or unchecked (False). So, if you bind it to a Boolean property, and set the binding mode to two-way, then the property will change depending on the state of the CheckBox.

To implement two-way binding to a static property, a standard binding procedure will not be the suitable solution. So, what steps you need to take to correctly bind the control property?

1. Refactor the class that contains the static property to be a singleton

What I am referring to in this case is the singleton pattern (more information can be found here). The singleton pattern main idea is to restrict the class instantiation just to one object, so only one instance is available.

To correctly implement the two-way binding, you need to change your class to be a singleton. Fortunately, this is done by adding just a few lines of code. Let’s take a look at a sample class (you can implement your own, if you want to). This one is the initial class (before refactoring):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestApp
{

	public class TestClass
	{

		public static bool testValue = true;

		public static bool TestValue
		{
			get { return testValue; }
			set { testValue = value; }
		}

	} 
}




We have a static Boolean TestValue property here. Basically, you can have properties of any type here, so you can implement it as string or anything else. The class can be instantiated multiple times; however, this creates more troubles when creating the two-way bindining. To solve this issue, let’s make the class a singleton. Take a look at the updated class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestApp
{

	public class TestClass
	{
		private static TestClass instance;

		public TestClass() { }

		public static TestClass Instance
		{
			get
			{
				if (instance == null)
				{
					instance = new TestClass();
				}
				return instance;
			}
		}

		public static bool testValue = true;

		public static bool TestValue
		{
			get { return testValue; }
			set { testValue = value; }
		}

	} 
}




The TestValue property is still in its place, but as you see, now there is a public constructor and an Instance property. This will ensure that only one instance of the class will be in use. Congratulations! A singleton is as easy as this.

2. Declare the proper class file namespace

The next step is declaring the namespace. You need to correctly declare the namespace of the class in the main XAML file, where the binding control will be placed. Just add this code as an attribute to the Windows element:

xmlns:<NamespaceID>="clr-namespace:<ClassNamespace>"



In my case, I used this:

xmlns:Classes="clr-namespace:TestApp"



This will make it possible to call the above class in the next parts of the code.

3. Add the key reference to the singleton

Now, you need to reference the singleton class in your XAML file, so you can use it in the binding control. If looking at my specific example with the test class, the code will look like this:

	<window.Resources>
			<Classes:TestClass x:Key="TClass"/>
	</window.Resources>



You have to declare the class and assign it a key, by which it will be identified later. The class should be a member of the above declared namespace. The key can be any name you want to assign.

4. Bind the control

In my example, I am going to bind a CheckBox control. The full XAML code for the control is the following:

	   <CheckBox IsChecked="{Binding Source={StaticResource TClass},Path=TestValue, Mode=TwoWay }" Height="29" HorizontalAlignment="Left" Margin="37,29,0,0" Name="checkBox1" VerticalAlignment="Top" Width="206" Checked="checkBox1_Checked" Unchecked="checkBox1_Unchecked">CheckBox</CheckBox>



Let’s take a look at the binding code:

"{Binding Source={StaticResource TClass},Path=TestValue, Mode=TwoWay }"



The actual resource is my test class, therefore, I am showing that the property I am trying to access is a member of TClass (that’s the key assigned to the class). The Path property in this case shows the name of the property that will be accessed. I would like to remind you, that the TestValue property is Boolean. And obviously, the explicit mode declaration shows that the binding will be in the two-way mode.

As you see, I also declared two event handlers for the CheckBox. Those were created to demonstrate the two-way binding is actually working. Let’s see the code for these event handlers:

		private void checkBox1_Checked(object sender, RoutedEventArgs e)
		{
			this.Title = TestApp.TestClass.testValue.ToString();
		}

		private void checkBox1_Unchecked(object sender, RoutedEventArgs e)
		{
			this.Title = TestApp.TestClass.testValue.ToString();
		}



Whenever the CheckBox is checked or unchecked, the window title will display the status of the TestValue property.

Now, run the application and see the two-way binding to a static property work!

Is This A Good Question/Topic? 1
  • +

Replies To: [WPF] Two-way Binding To A Static Property

#2 PsychoCoder  Icon User is offline

  • Google.Sucks.Init(true);
  • member icon

Reputation: 1637
  • View blog
  • Posts: 19,853
  • Joined: 26-July 07

Posted 27 August 2009 - 04:42 PM

Excellent tutorial! Nice work
Was This Post Helpful? 0
  • +
  • -

#3 trickett  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 07-November 09

Posted 07 November 2009 - 03:44 AM

Hi,

Just stumbled across this article looking for info on xaml binding and thought I should point out that the code provided for a singleton isn't actually quite right. The singleton pattern has to have a private constructor with a static method that returns the instance. All that the code here does is to create an instance property. If you actually do make the class a singleton, the binding fails because it cannot create an instance of the class as the constructor is private.

Hate to quote wikipedia but here is a link to more info on the singleton pattern;

http://en.wikipedia....ngleton_pattern
Was This Post Helpful? 0
  • +
  • -

#4 Deviltreh  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 03-December 11

Posted 03 December 2011 - 11:17 AM

What if static property is in TestClass subclass?

public class TestClass
	{
		private static TestClass _instance;

		public static TestClass Instance
		{
			get { return _instance ?? (_instance = new TestClass()); }
		}
		
		public class TestSubClass
		{

			private TestSubClass _instance;

			public static TestSubClass Instance
			{
				get { return _instance ?? (_instance = new TestSubClass()); }
			}
			
			static static bool _testValue = true;
			public static bool TestValue
			{
				get { return _testValue; }
				set { _testValue = value; }
			}
		}
	}


"{Binding Source={StaticResource TClass},Path=TestSubClass.TestValue, Mode=TwoWay }"

is the only thing my newbie brain could come up with and it obviously doesn't work.
Was This Post Helpful? 0
  • +
  • -

#5 Draken302  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 05-September 12

Posted 05 September 2012 - 02:08 AM

Singleton instance has often private constructor, then you could'nt use a window.Resource

For example I use this (Resource is'nt necessary):
<TextBlock ..........
Text="{Binding Source={x:Static Support:UserLogin.Instance}, Path=Name, Mode=OneWay}" />

Where: Support is Namespace (xmlns:Support=.....)
UserLogin is a Singleton class with private construktor and static property Instance
Name is public property on UserLogin class

UserLogin class must implement INotifyPropertyChanged interface for changing properties.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1