我有一个带有名为CanSeePhotos的布尔静态属性的类,这应该控制我的DataTemplate中图片的可见性.出于调试目的,我将"CanSeePhotos"绑定到DataTemplate中的文本块.
我想做的是:
我的问题是如果我在InitializeComponent()之后设置CanSeePhotos = true,那么数据仍然显示为CanSeePhotos为false(如果我在它工作正常之前这样做).这是为什么?如何修复它以便我可以在加载数据之前的任何时候设置值?
这是我如何绑定到我的DataTemplate中的静态变量:
<TextBlock Text="{Binding Source={x:Static DAL:LoggedInUser.CanSeePhotos}, Mode=OneWay}"/>
Run Code Online (Sandbox Code Playgroud)
这是LoggedInUser类:
public class LoggedInUser
{
public static bool CanSeePhotos { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果我将控件的可见性直接绑定到静态属性,它将根据属性的值显示/折叠:
Visibility="{Binding Source={x:Static DAL:LoggedInUser.CanSeePhotos}, Converter={StaticResource BooleanToVisibilityConverter}}"
Run Code Online (Sandbox Code Playgroud)
但我需要像这样使用DataTrigger:
<DataTrigger Binding="{Binding Source={x:Static DAL:LoggedInUser.CanSeePhotos}}" Value="true">
<Setter TargetName="icon" Property="Source" Value="{Binding Photo}"/>
</DataTrigger>
Run Code Online (Sandbox Code Playgroud)
在上面的情况下,如果属性为true,则setter永远不会被设置.
是什么赋予了?
这里有三个注意事项:
考虑1:该物业没有变更通知
可以在InitializeComponent()调用期间评估某些数据绑定,稍后再评估其他数据绑定.您正在请求在InitializeComponent()返回后设置CanSeePhotos的功能.如果没有任何更改通知,则在InitializeComponent()期间评估的任何绑定都将具有原始值,并且不会更新.之后评估的任何绑定(例如在DataBind优先级)将具有新值.要在所有情况下都能使用此功能,您需要某种更改通知.
使用以"{get; set;}"声明的.NET Framework属性将不起作用,因为该属性没有机制在其值发生更改时通知任何人.实际上有两种非常偷偷摸摸的方法可以从标准的.NET Framework属性(MarshalByRefObject和IL重写)获取通知,但它们对于您的情况来说太复杂了.
考虑2:该属性是静态的
.NET Framework有几个属性更改通知机制(DependencyProperty,INotifyPropertyChanged等),但没有任何内置机制支持静态属性的更改通知.因此,如果不创建用于发送更改信号的新机制,则不能使用静态属性(例如,您可以拥有一个包装属性的对象).
考虑3:DataTriggers共享一个Binding
设置Visibility时,每次都构建一个新的Binding,因此它获取LoggedInUser.CanSeePhotos的最新值.
在创建DataTrigger时,WPF在加载触发器时构造单个Binding并将其用于每个对象.当加载包含DataTrigger的资源字典时,可以在应用程序启动时构建此Binding,因此它将始终获取CanSeePhotos的默认值.这是因为Source =将一个实际对象分配给绑定(它的计算不是延迟的).所以每个Binding都是用Source = true或Source = false构造的.
推荐解决方案
将DependencyObject与DependencyProperty一起使用,并从静态属性引用它,如下所示:
public class LoggedInUser : DependencyObject
{
// Singleton pattern (Expose a single shared instance, prevent creating additional instances)
public static readonly LoggedInUser Instance = new LoggedInUser();
private LoggedInUser() { }
// Create a DependencyProperty 'CanSeePhotos'
public bool CanSeePhotos { get { return (bool)GetValue(CanSeePhotosProperty); } set { SetValue(CanSeePhotosProperty, value); } }
public static readonly DependencyProperty CanSeePhotosProperty = DependencyProperty.Register("CanSeePhotos", typeof(bool), typeof(LoggedInUser), new UIPropertyMetadata());
}
Run Code Online (Sandbox Code Playgroud)
该类将始终具有一个实例,该实例将可用作LoggedInUser.Instance.所以它有点像静态类.区别在于,LoggedInUser.Instance具有DependencyProperty,因此当您修改属性时,它可以通知任何感兴趣的各方.WPF的Binding将注册此通知,因此您的UI将更新.
上面的代码将在XAML中像这样使用:
Visibility="{Binding CanSeePhotos, Source={x:Static LoggedInUser.Instance}, Converter=...
Run Code Online (Sandbox Code Playgroud)
在您的代码隐藏中如果您需要访问CanSeePhotos,它将是,例如:
LoggedInUser.Instance.CanSeePhotos = true;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7985 次 |
| 最近记录: |