Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding static property and implementing INotifyPropertyChanged

I'm trying to bind a static property of some class to some control. I've tryied a few implementation but each has its problem:

All examples use the next XAML:

 <Label Name="label1" Content="{Binding Path=text}"/>  

1st approach - don't use INotifyPropertyChanged

public class foo1
{
    public static string text { get; set; }
}

The problem is that when 'text' propery changes the control is not notified.

Second approach - use INotifyPropertyChanged

public class foo1 : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    private static string _text;
    public static string text
    {
        get { return _text; }
        set
        {
            _text = value;
            OnPropertyChanged("text");
        }
    }
}

This doesn't compile because OnPropertyChanged() method is not static and it's called within a static method.

Second approach try 2: make OnPropertyChanged() method static => this doesn't compile because OnPropertyChanged() is now static and it tries to use 'PropertyChanged' event which is not static.

Second approach try 3: make 'PropertyChanged' event static => this doesn't compile because the class does not implement 'INotifyPropertyChanged.PropertyChanged' event (the event is defined in 'INotifyPropertyChanged interface is not static but here it is static).

At this point I gave up.

Any Ideas?

like image 415
dana Avatar asked Dec 09 '22 11:12

dana


2 Answers

I'd suggest you just have an instance-property return your static property like this:

private static string _text;
public string text
{
    get { return _text; }
    set
    {
        _text = value;
        OnPropertyChanged("text");
    }
}

However this makes the whole binding comparatively pointless since change notifications are only created in one instance of the class and not every instance. Thus only bindings which bind to the property on the specific instance on which it was changed will update.

A better method would be using a singleton as can be seen here.

like image 168
H.B. Avatar answered Feb 09 '23 01:02

H.B.


Using a singleton is going to be the easiest and cleanest to implement. If you want to go the hard way without using a singleton you can use the following.

Create a static PropertyChangedEventHandler that gets called from your static property. When you create a new instance of your class, register to receive a call back from the static event. When you get the callback, call OnPropertyChanged("text"). The BIG problem with this is you need to use a WeakReference when you register for the static event. Otherwise your object will stay around forever. I skipped this step in the code.

The reason you need to forward to the instance-event is because who ever registered the NotifyPropertyChanged needs to know who the 'sender' (ie the instance of foo1 with the instance-property on it)

public class foo1 : System.ComponentModel.INotifyPropertyChanged
{
    // static property
    private static string _text = "static string";
    public static string static_text
    {
        get
        {
            return _text;
        }
        set
        {
            _text = value;
            OnStaticPropertyChanged("static_text");
        }
    }
    private static System.ComponentModel.PropertyChangedEventHandler staticpropChanged;
    static protected void OnStaticPropertyChanged(string pname)
    {
        System.ComponentModel.PropertyChangedEventArgs e = new System.ComponentModel.PropertyChangedEventArgs(pname);
        System.ComponentModel.PropertyChangedEventHandler h = staticpropChanged;
        if (h != null)
            h(null, e);

    }
    public foo1()
    {
        // really should use a weakreference here.. but leaving it out
        // for simplicity
        staticpropChanged += foo1_staticpropChanged;
    }

    void foo1_staticpropChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        // map the static name to the instance name
        if(e.PropertyName == "static_text") OnPropertyChanged("text");
    }
    // instance-property forwards to static
    public string text
    {
        get { return foo1.static_text; }
        set { foo1.static_text = value; }
    }
like image 24
shimpossible Avatar answered Feb 09 '23 00:02

shimpossible