gpt4 book ai didi

WPF - DataTemplate 绑定(bind)到静态成员

转载 作者:行者123 更新时间:2023-12-05 00:08:17 25 4
gpt4 key购买 nike

我有一个名为 CanSeePhotos 的具有 bool 静态属性的类,它应该控制我的 DataTemplate 中图片的可见性。
出于调试目的,我将“CanSeePhotos”绑定(bind)到 DataTemplate 中的文本 block 。

我想做的是:

  • 初始化组件()
  • 根据登录用户
  • 设置CanSeePhotos
  • 加载数据并适当显示

  • 我的问题是,如果我在 InitializeComponent() 之后设置 CanSeePhotos = true,则数据仍然显示为 CanSeePhotos 为 false(如果我在它正常工作之前这样做)。这是为什么?如何修复它以便我可以在加载数据之前的任何时候设置值?

    下面是我如何绑定(bind)到我的 DataTemplate 中的静态变量:
    <TextBlock Text="{Binding Source={x:Static DAL:LoggedInUser.CanSeePhotos}, Mode=OneWay}"/>

    这是 LoggedInUser 类:
    public class LoggedInUser
    {
    public static bool CanSeePhotos { get; set; }
    }

    编辑:
    如果我将控件的可见性直接绑定(bind)到静态属性,它将根据属性的值显示/折叠:
    Visibility="{Binding Source={x:Static DAL:LoggedInUser.CanSeePhotos}, Converter={StaticResource BooleanToVisibilityConverter}}"

    但我需要像这样使用 DataTrigger:
    <DataTrigger Binding="{Binding Source={x:Static DAL:LoggedInUser.CanSeePhotos}}" Value="true">
    <Setter TargetName="icon" Property="Source" Value="{Binding Photo}"/>
    </DataTrigger>

    在上述情况下,如果属性为真,则 setter 永远不会被设置。

    是什么赋予了?

    最佳答案

    这里有三个考虑:

    考虑一:该属性(property)无变更通知

    一些数据绑定(bind)可能会在 InitializeComponent() 调用期间进行评估,而其他数据绑定(bind)将在稍后进行评估。您正在请求在 InitializeComponent() 已经返回后设置 CanSeePhotos 的能力。如果没有任何更改通知,则在 InitializeComponent() 期间评估的任何绑定(bind)都将具有原始值并且不会被更新。之后评估的任何绑定(bind)(例如 DataBind 优先级)都将具有新值。为了在所有情况下都能正常工作,您需要某种更改通知。

    使用用“{ get; set; }”声明的 NET Framework 属性将不起作用,因为该属性没有在其值发生更改时通知任何人的机制。实际上有两种非常狡猾的方法可以从标准 NET Framework 属性(MarshalByRefObject 和 IL 重写)获取通知,但它们对于您的情况来说太复杂了。

    考虑2:属性是静态的

    NET Framework 具有多种属性更改通知机制(DependencyProperty、INotifyPropertyChanged 等),但没有一个内置机制支持静态属性的更改通知。因此,如果不创建新的信号更改机制(例如,您可以有一个包装该属性的对象),您就不能为此使用静态属性。

    注意事项 3:DataTriggers 共享一个 Binding

    设置 Visibility 时,您每次都在构建一个新的 Binding,因此它会获取 LoggedInUser.CanSeePhotos 的最新值。

    创建 DataTrigger 时,WPF 会在加载触发器时构造一个 Binding 并将其用于每个对象。这个 Binding 是在加载包含 DataTrigger 的资源字典时构建的,可能是在应用启动时,所以它总是会获取 CanSeePhotos 的默认值。这是因为 Source= 将实际对象分配到绑定(bind)中(其计算不会延迟)。因此,每个绑定(bind)都是使用 Source=true 或 Source=false 构建的。

    推荐解决方案

    使用带有 DependencyProperty 的 DependencyObject 并从静态属性中引用它,如下所示:

    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());

    }

    此类将始终具有一个实例,并且该实例将作为 LoggedInUser.Instance 提供。所以它有点像一个静态类。不同之处在于,LoggedInUser.Instance 有一个 DependencyProperty,因此当您修改该属性时,它可以通知任何相关方。 WPF 的绑定(bind)将注册此通知,因此您的 UI 将被更新。

    上面的代码将在 XAML 中像这样使用:
    Visibility="{Binding CanSeePhotos, Source={x:Static LoggedInUser.Instance}, Converter=...

    在您的代码隐藏中,如果您需要访问 CanSeePhotos,例如:
    LoggedInUser.Instance.CanSeePhotos = true;

    关于WPF - DataTemplate 绑定(bind)到静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1689878/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com