Sunday, January 27, 2013

WPF Binding to a Static Property

In WPF, the binding provides an efficient and easy way of data interaction between components. Every FrameworkElement can be bound to any data sources in the form of XAML and CLR.

The binding technique is one of the best way to simplify the implementations in WPF. But you should understand that every class in .NET only participates in two way binding if you have implemented the IPropertyChanged interface or you used DependencyProperty object.

Binding to a Static Property

Binding to static property of the class is slightly complex than normal binding. If you have a class with static property, you atleast need to address the requirement whether the binding is one or two dimensional. Please note that static property is not an instance type property and you should do your own trick to notify the changes in the XAML.

First of all, we should create a class (note: don't make it static). Then, place all static property you wish to put in this class. In our case, we will name the class StaticBinder and will put three property named MSG_OK, MSG_Cancel and MSG_Welcome. See below the implementation.

public class StaticBinder
{
    static StaticBinder()
    {
        MSG_Cancel = "Welcome";
        MSG_OK = "OK";
        MSG_Welcome = string.Format("Welcome {0}!", "WPF Binding");
    }

    public static string MSG_Cancel
    {
        get;
        set;
    }

    public static string MSG_OK
    {
        get;
        set;
    }

    public static string MSG_Welcome
    {
        get;
        set;
    }
}

You will notice that we created one static constructor. In there, we place all the property initialization and call each of them statically. Now, in the XAML, we need to create a Window with Label and Button controls embedded that can be bound on the class above. See below our implementation.

<Window x:Class="CodesDirectory.WIN_StaticBinding"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WIN Static Binding" Height="300" Width="300"
        WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Label Grid.Row="0"></Label>
        <StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
            <Button Name="okayButton"
                    Click="okayButton_Click"
                    Width="100"
                    Margin="5"></Button>
            <Button Name="cancelButton"
                    Width="100"
                    Margin="5"></Button>
        </StackPanel>
    </Grid>
</Window>

Now before you can participate your Window in the binding, you should create a reference to the class we created above via XAML. You should put an xmlns (XML Namespace) that directs to the namespace where the StaticBinder class resides, and you should create a new instance of StaticBinder class and put it in the Window resources. See below the additional codes in yellow background.

<Window x:Class="CodesDirectory.WIN_StaticBinding"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WIN Static Binding" Height="300" Width="300"
        xmlns:classes="clr-namespace:CodesDirectory.Classes"
        WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Window.Resources>
        <ObjectDataProvider x:Key="staticBinder"
                            ObjectType="{x:Type classes:StaticBinder}"></ObjectDataProvider>
    </Window.Resources>
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Label Grid.Row="0"></Label>
        <StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
            <Button Name="okayButton"
                    Click="okayButton_Click"
                    Width="100"
                    Margin="5"></Button>
            <Button Name="cancelButton"
                    Width="100"
                    Margin="5"></Button>
        </StackPanel>
    </Grid>
</Window>

With the XAML codes above, you will notice that our namespace name is 'classes'. You can change it in any name if you wish. Also, we created a new object named ObjectDataProvider with key value staticBinder. The ObjectDataProvider is an object that provides us a dynamic resource data binder in the XAML. It can also be used to instantiate and call the class methods in your application.

Let's continue to the actual binding. Now in the Content property of the Button and Label, use the StaticResource that connects the ObjectDataProvider and set the Path property equal to the actual Property of the StaticBinder class. See below the codes in yellow background.

<Window x:Class="CodesDirectory.WIN_StaticBinding"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WIN Static Binding" Height="300" Width="300"
        xmlns:classes="clr-namespace:CodesDirectory.Classes"
        WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Window.Resources>
        <ObjectDataProvider x:Key="staticBinder"
                            ObjectType="{x:Type classes:StaticBinder}"></ObjectDataProvider>
    </Window.Resources>
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Label Grid.Row="0"
               Content="{Binding Source={StaticResource ResourceKey=staticBinder}, Path=MSG_Welcome}"></Label>
        <StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
            <Button Name="okayButton"
                    Click="okayButton_Click"
                    Content="{Binding Source={StaticResource ResourceKey=staticBinder}, Path=MSG_OK}"
                    Width="100"
                    Margin="5"></Button>
            <Button Name="cancelButton"
                    Content="{Binding Source={StaticResource ResourceKey=staticBinder}, Path=MSG_Cancel}"
                    Width="100"
                    Margin="5"></Button>
        </StackPanel>
    </Grid>
</Window>

Please note that the implementation above doesn't participates in the two directional binding. Any changes happens on the StaticBinder class property will not reflect in the UI. Please continue read the blog WPF Binding to Static Instance if you wish to understand how to implement two directional binding.

2 comments:

  1. ----------C# CODE BEHIND ----------
    namespace SolepadSettings
    {

    public static class Parameters
    {
    static Parameters()
    {
    IsBluethON = true;
    }
    public static bool IsBluethON { set; get; }
    }
    }

    ----- WPF ------











    I'm changing the state of IsBluethON from another event, but the binding won't work?

    if ((bytRxData[14] & 0x10) == 0x10)
    Parameters.IsBluethON = true;
    else
    Parameters.IsBluethON = false;

    Can anyone correct where I'm doing it wrong?

    Thanks
    John

    ReplyDelete
  2. Wonder why WPF code is not shown??

    ReplyDelete

Place your comments and ideas