静态属性绑定最初只工作一次
本文关键字:一次 工作 属性 绑定 静态 | 更新日期: 2023-09-27 18:36:36
我在将静态字符串属性绑定到 WPF 应用程序中的文本块时遇到问题。最初它正确设置了值,但我有一个更新值的方法,但更改不会反映在 UI 上。
我已经在线获取了 StaticPropertyChanged 代码,所以我的实现方式可能存在问题?
我确定这是我缺少的简单内容,因为我对 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}}">
谢谢:)
绑定需要在Binding
中使用Path
值。对于绑定到静态属性,它们需要非常具体的语法。在你的例子中,XAML 应如下所示:
<TextBlock Name="Test"
Text="{Binding Path=(status:Status.IsConnected), Mode=TwoWay}">
请注意在路径周围使用括号。这指示解析器正确解释类名。
您的代码隐藏是正确的。您已经实现了单个 StaticPropertyChanged
事件,类似于实例版本 PropertyChanged
,并且 WPF 将使用该事件进行绑定。请注意,您也可以改为实现IsConnectedChanged
事件。WPF也会接受这一点。
最后,我注意到我读过的指南建议在可能和/或适当的情况下使用单例模式。虽然 WPF 现在支持绑定到静态属性,但绑定到实际对象上的属性仍然是首选。
有关更多详细信息,请参阅此相关博客文章:WPF 4.5:静态属性的绑定和更改通知
编辑:
您没有询问如何在代码隐藏中创建绑定。但是,由于我今天早些时候正在研究一个涉及在代码隐藏中设置绑定的不同问题,因此我决定研究如何将其用于静态属性。
对于实例属性,这很简单,因为您可以为 Binding.Source
属性指定对象。但对于静态属性,这是null
(*)。相反,您必须通过 Binding.Path
属性指定属性:
Binding binding = new Binding();
binding.Path = new PropertyPath(typeof(Status).GetProperty("IsConnected");
binding.Mode = BindingMode.TwoWay;
这会将表示要绑定到的属性的 PropertyInfo
对象传递给 PropertyPath(object)
构造函数重载。
(*)或者更确切地说,它可以为空。绑定到静态属性时可以使用的一种技巧是指定包含静态属性的类的实际实例。当然,您不能为static
类或碰巧没有方便的实例可以使用的类执行此操作。但是,如果这样做,则实际上可以绑定到静态属性,就像绑定到实例属性一样,指定包含静态属性的类的任何实例以及静态属性的名称(就像它是实例属性一样)。
两件事:
-
自定义事件不会告知 UI 属性已更改。您必须实现
INotifyPropertyChanged
接口并引发PropertyChanged
事件。这可以通过将处理程序注册到您的 StaticPropertyChangedStatus
类中以及从处理程序调用中PropertyChanged(null, new PropertyChangedEventArgs("IsConnected"));
的 InotifyPropertyChanged -
其次,如果你的 Status 类不是静态的,那么你不需要使用 x:Static 来绑定它。如果你在 DataContext 中有 Status 类的实例,你可以直接绑定到它的静态属性,如
<TextBlock Name="Test" Text="{Binding Status.IsConnected}"/>
此处假设您的DataContext
包含类类型的属性状态Status
。
如果 Status 类实例是您DataContext
则可以直接绑定IsConnected
作为<TextBlock Name="Test" Text="{Binding IsConnected}"/>
窗口资源中添加状态类资源,如下所示:
<Window.Resources>
<local:Status x:Key="StatusManager"/>
</Window.Resources>
现在像这样绑定你的 IsConnected 到 TextProperty:
<TextBlock Name="Test"
Text="{Binding Source={StaticResource StatusManager}, Path=IsConnected}"
我认为没有必要以这种方式尝试事件
<TextBlock Name="Test"
Text="{x:Static Member:namspacename.AppName.bool}">
出于何种原因,我都无法使静态绑定工作,但我能够使用单例正确绑定它。
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}">