静态 属性 绑定最初只工作一次

Static property bind only works once initially

我在将静态字符串 属性 绑定到 WPF 应用程序中的文本块时遇到问题。 最初它正确设置了值,但我有一个更新值的方法,但更改没有反映在 UI.

我已经在网上获取了静态属性更改的代码,所以我的实现方式可能存在问题?

我确定我缺少的是一些简单的东西,因为我对 WPF 还很陌生。

感谢任何帮助!

属性 问题:

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

谢谢:)

我认为没有必要尝试这种方式

<TextBlock Name="Test"
           Text="{x:Static Member:namspacename.AppName.bool}">

两件事:

  1. 您的自定义事件不会告诉 UI 属性 已更改。您将必须实现 INotifyPropertyChanged 接口并引发 PropertyChanged 事件。这可以通过将处理程序注册到 Status class 中的 StaticPropertyChanged 并从处理程序调用中完成 PropertyChanged(null, new PropertyChangedEventArgs("IsConnected")); 的 INotifyPropertyChanged

  2. 其次,如果您的 Status class 不是静态的,那么您不需要使用 x:Static 来绑定它。如果你的 DataContext 中有 Status class 实例,你可以直接绑定到它的静态 属性 like

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

这里假设您的 DataContext 包含 属性 类型 Status class.

的状态

如果 Status class 实例是您的 DataContext 那么您可以直接将 IsConnected 绑定为 <TextBlock Name="Test" Text="{Binding IsConnected}"/>

无论出于何种原因,我都无法使静态绑定正常工作,但我能够使用 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));
    }
}

和 XAML:

        <TextBlock Name="Test"
                   DataContext="{x:Static status:Global.Instance}"
                   Text="{Binding Path=IsConnected}">

在 Window 资源中添加状态 class 资源,如下所示:

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

现在将您的 IsConnected 绑定到 TextProperty,如下所示:

<TextBlock Name="Test"
       Text="{Binding Source={StaticResource StatusManager}, Path=IsConnected}"

双向绑定需要使用 Binding 中的 Path 值。为了绑定到静态属性,它们需要非常特定的语法。在您的情况下,XAML 应该如下所示:

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

请注意路径两边的括号。这指示解析器正确解释 class 名称。

您的代码隐藏是正确的。您已经实现了一个 StaticPropertyChanged 事件,类似于实例版本 PropertyChanged,WPF 将使用哪个事件进行绑定。请注意,您也可以改为实施 IsConnectedChanged 事件。 WPF 也会接受这一点。

最后我注意到,我读过的指南建议尽可能 and/or 使用单例模式。虽然 WPF 现在支持绑定到静态属性,但仍然首选绑定到实际对象上的 属性。

有关详细信息,请参阅此相关博客 post:WPF 4.5: Binding and change notification for static properties


编辑:

您没有询问如何在代码隐藏中创建绑定。但是,因为今天早些时候我正在研究一个不同的问题,涉及在代码隐藏中设置绑定,所以我决定研究这对静态属性是如何工作的。

对于实例属性,很简单,因为你可以为Binding.Source属性指定一个对象。但是对于静态 属性,这是 null (*)。相反,您必须通过 Binding.Path 属性:

指定 属性
Binding binding = new Binding();

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

这会将表示您要绑定到的 属性 的 PropertyInfo 对象传递给 PropertyPath(object) 构造函数重载。


(*) 或者更确切地说,它 可以 为空。绑定到静态属性时可以使用的一种技巧是指定包含静态 属性 的 class 的实际实例。当然,您不能对 static classes 或 classes 执行此操作,因为您碰巧没有可用的方便实例。但如果这样做,那么您实际上可以绑定到静态 属性,就像绑定到实例 属性 一样,指定包含静态 属性 的 class 的任何实例],以及静态的名称 属性(就好像它是一个实例 属性)。