绑定静态属性并实现INotifyPropertyChanged

时间:2011-01-13 12:50:56

标签: wpf data-binding inotifypropertychanged

我正在尝试将某个类的静态属性绑定到某个控件。我尝试了一些实现,但每个都有它的问题:

所有示例都使用下一个XAML:

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

第一种方法 - 不要使用INotifyPropertyChanged

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

问题是,当'text'propery改变时,控制权不会被通知。

第二种方法 - 使用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");
        }
    }
}

这不能编译,因为OnPropertyChanged()方法不是静态的,而是在静态方法中调用。

第二种方法尝试2:make OnPropertyChanged()方法static =&gt;这不能编译,因为OnPropertyChanged()现在是静态的并且它试图使用非Property的'PropertyChanged'事件。

第二种方法尝试3:使'PropertyChanged'事件静态=&gt;这不会编译,因为该类没有实现'INotifyPropertyChanged.PropertyChanged'事件(该事件在'INotifyPropertyChanged接口中定义不是静态的,但在这里它是静态的。)

此时我放弃了。

任何想法?

3 个答案:

答案 0 :(得分:11)

我建议你只需要一个instance-property返回你的静态属性:

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

然而,这使得整个绑定相对毫无意义,因为更改通知仅在类的一个实例中创建,而不是在每个实例中创建。因此,只有绑定到更改它的特定实例上的属性的绑定才会更新。

更好的方法是使用单身,如here所示。

答案 1 :(得分:2)

使用单例将是最简单,最干净的实现方式。如果你想在不使用单身的情况下艰难前行,可以使用以下内容。

创建一个从静态属性调用的静态PropertyChangedEventHandler。创建类的新实例时,请注册以从静态事件接收回调。获得回调时,请调用OnPropertyChanged(“text”)。 这是一个很大的问题,你需要在注册静态事件时使用WeakReference。否则你的对象将永远存在。我在代码中跳过了这一步。

你需要转发到实例事件的原因是因为谁注册了NotifyPropertyChanged需要知道谁是'sender'(即foo1的实例,其上有instance-property)

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; }
    }

答案 2 :(得分:0)

    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; }
    }

这样我就不必在事件中做任何处理。 这对于为我的整个程序创建一个状态栏并在我不断扩展的程序中从任何地方和任何用户控件更新它都非常有帮助。

谢谢你的光明