0

I'm having problems binding a static string property to textblock in a WPF application. Initially it sets the value correctly but I have a method that is updating the value, but the changes are not reflected on the UI.

I have sourced the StaticPropertyChanged code online, so potentially there is an issue with how I've implemented it?

I'm sure it's something simple i'm missing, as i'm very new to WPF.

Any help is appreciated!

Property in question:

private static string _isConnected = "Initial Value";

public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

public static string IsConnected
{
    get { return _isConnected; }
    set
    {
        _isConnected = value;
        if (StaticPropertyChanged != null)
            StaticPropertyChanged(null, new PropertyChangedEventArgs("IsConnected"));
    }
}

XAML:

<TextBlock Name="Test"
           Text="{Binding Source={x:Static status:Status.IsConnected}}">

Thanks :)

orangey
  • 55
  • 7

5 Answers5

1

Two things:

  1. Your custom event is not going to tell UI that property has changed. You will have to implement INotifyPropertyChanged interface and raise PropertyChanged event. This you can do by registering the handler to your StaticPropertyChanged in Status class and from the handler call PropertyChanged(null, new PropertyChangedEventArgs("IsConnected")); of INotifyPropertyChanged

  2. Secondly, if your Status class is not static then you don't need to use x:Static to bind it. If you have instance of Status class with you in your DataContext, you can directly bind to its static property like

     <TextBlock Name="Test" Text="{Binding Status.IsConnected}"/>
    

Here assuming your DataContext contains property Status of type Status class.

If Status class instance is your DataContext then you can directly bind the IsConnected as <TextBlock Name="Test" Text="{Binding IsConnected}"/>

Nitin
  • 18,344
  • 2
  • 36
  • 53
  • Oh! Thanks for the explanation, I didn't really know what was going on. I'll have a look at making the changes you suggested now :) – orangey Jan 07 '15 at 06:42
1

Add Status class resource in Window Resources like this :

<Window.Resources>
    <local:Status x:Key="StatusManager"/>
</Window.Resources>

And now bind your IsConnected to TextProperty like this :

<TextBlock Name="Test"
       Text="{Binding Source={StaticResource StatusManager}, Path=IsConnected}"
Amol Bavannavar
  • 2,062
  • 2
  • 15
  • 36
1

Two-way bindings require use of the Path value in the Binding. For binding to static properties, they require a very specific syntax. In your case, the XAML should look like:

<TextBlock Name="Test"
           Text="{Binding Path=(status:Status.IsConnected), Mode=TwoWay}">

Note the use of parentheses around the path. This indicates to the parser to interpret the class name correctly.

Your code-behind is correct. You have implemented a single StaticPropertyChanged event, analogous to the instance version PropertyChanged, and which WPF will use for the binding. Note that you could also have implemented an IsConnectedChanged event instead. WPF would have accepted that as well.

Finally I note that guidance I've read recommends using a singleton pattern if possible and/or appropriate. While WPF now supports binding to static properties, binding to a property on an actual object is still preferred.

See this relevant blog post for more details: WPF 4.5: Binding and change notification for static properties


EDIT:

You didn't ask about how to create a binding in code-behind. However, because I was looking at a different question earlier today involving setting up a binding in code-behind, I decided to look into how this would work for static properties.

For instance properties, it's simple because you can specify an object for the Binding.Source property. But for a static property, this is null (*). Instead, you have to specify the property via the Binding.Path property:

Binding binding = new Binding();

binding.Path = new PropertyPath(typeof(Status).GetProperty("IsConnected");
binding.Mode = BindingMode.TwoWay;

This passes a PropertyInfo object representing the property you're binding to, to the PropertyPath(object) constructor overload.


(*) Or rather, it can be null. A sort of hack you can use when binding to static properties is to specify an actual instance of the class containing the static property. Of course, you can't do this for static classes, or for classes for which you don't happen to have a handy instance lying around to use. But if you do, then you can actually bind to the static property just like you'd bind to an instance property, specifying any instance of the class containing the static property, and the name of the static property (as if it were an instance property).

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thanks for taking the time to explain it all, that makes far more sense than some of the waffle I've been reading online :) ! I've continued to use the singleton pattern, but I did try and implement your changes and I was able to successfully bind directly to the static property also. Thanks again! – orangey Jan 08 '15 at 01:46
0

i think no need of event try this way

<TextBlock Name="Test"
           Text="{x:Static Member:namspacename.AppName.bool}">
vijay.k
  • 179
  • 1
  • 10
0

I wasn't able to get the static binding to work for whatever reason, but I was able to bind it correctly using a Singleton.

public class Global : INotifyPropertyChanged
{
    private static  Global _instance = new Global();

    public static Global Instance
    {
        get { return _instance; }
    }

    private string _isConnected;

    public string IsConnected
    {
        get { return _isConnected; }
        set
        {
            _isConnected = value;
            OnPropertyChanged("IsConnected");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

And the XAML:

        <TextBlock Name="Test"
                   DataContext="{x:Static status:Global.Instance}"
                   Text="{Binding Path=IsConnected}">
orangey
  • 55
  • 7
  • This is the preferred approach if it fits with your architecture. However, note that it is possible in .NET 4.5 and later to successfully bind to a static property. Please see my answer to your question for details. – Peter Duniho Jan 07 '15 at 08:17