简体   繁体   中英

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?

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 .

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; }
    }
    public static String StatusInformation
    {
        get { return _StatusInformation; }
        set { _StatusInformation = value; OnStaticPropertyChanged("StatusText"); }
    }

    #region Handlig Static Properties Changed
    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);

    }
    private void Handler_PropertyChange(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        NotifyPropertyChanged(e.PropertyName);
    }
    #endregion
    public string StatusText
    {
        get { return ExchangeServices.StatusInformation; }
        set { ExchangeServices.StatusInformation = value; }
    }

this way i didnt have to do any handling in the event at all. this was really helpfull to create one status bar for my entire program and update it from anywhere and any user control in my ever expanding program.

Thank you to shimpossible

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM