【问题标题】:Static property not updating in UI静态属性未在 UI 中更新
【发布时间】:2017-06-25 22:38:03
【问题描述】:

我花了最后一个小时试图在 google 和 stackoverflow 中找到答案。我遵循了不同的建议和建议,但到目前为止没有任何效果。我当前的代码如下所示:

public class GlobalManager : ViewModelBase
{
    static object _LockObject_GFS = new object();
    static double _GlobalFontSize;
    public static double GlobalFontSize
    {
        get
        {
            lock (_LockObject_GFS)
            {
                _GlobalFontSize = GetGlobalResource<double>(LambdaHelper.MemberToString(() => GlobalFontSize));
                return _GlobalFontSize;
            }
        }
        set
        {
            lock (_LockObject_GFS)
            {
                if (_GlobalFontSize != value)
                {
                    _GlobalFontSize = value;
                    SetGlobalResource(value, LambdaHelper.MemberToString(() => GlobalFontSize));
                    NotifyStaticPropertyChanged(() => GlobalFontSize);
                }
            }
        }
    }
}

getter 和 setter 都被调用。 NotifyStaticPropertyChanged 有效,我的 UI 没有更新。我添加了一个TextBlock 来检查它是否更新。显然没有。

<TextBlock Text="{Binding Path=(global:GlobalManager.GlobalFontSize), Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

如果我在我的 VM(当前 DataContext)中定义一个属性,并将其绑定到 TextBlock,它会正确更新为当前值。

目前SliderDependencyProperty Value 绑定到此属性以更新字体大小。 (IsSnapToTickEnabled="True")

public double GlobalFontSize
{
    get { return GlobalManager.GlobalFontSize; }
    set { GlobalManager.GlobalFontSize = value; NotifyPropertyChanged(() => GlobalFontSize); }
}

如何让绑定与静态属性一起正常工作? StaticPropertyChanged 事件不为空。

StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));

编辑 1:

public static void NotifyStaticPropertyChanged(string propertyName)
{
    StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
}

public static void NotifyStaticPropertyChanged<T>(Expression<Func<T> > property)
{
    var expr = property.Body as MemberExpression;
    if (expr == null)
        throw new ArgumentException("Lambda does not contain member expression. () => MyClassOrObject.Property");
    NotifyStaticPropertyChanged(expr.Member.Name);
}

【问题讨论】:

  • @mm8 The StaticPropertyChanged event is not null.我的签名是正确的。
  • 您的 NotifyStaticPropertyChanged 方法是如何实现的?
  • @mm8 就像“正常”实现一样。查看我的编辑。
  • 我不喜欢使用static 属性和绑定的整个想法。而是使用单例 (GlobalManager.Instance.GlobalFontSize),然后您可以绑定到返回 instancestatic 属性,这是一个普通的 ViewModel 或实现 INotifyPropertyChanged 的事件模型。这种方式上升的通知是直截了当的,而且它会起作用。

标签: c# wpf xaml static inotifypropertychanged


【解决方案1】:

确保您的 GetGlobalResourceSetGlobalResource 方法按预期工作并且您的事件签名正确。

您可以参考下面的工作示例实现并将其与您的进行比较:

public class GlobalManager
{
    static object _LockObject_GFS = new object();
    static double _GlobalFontSize;
    public static double GlobalFontSize
    {
        get
        {
            lock (_LockObject_GFS)
            {
                return _GlobalFontSize;
            }
        }
        set
        {
            lock (_LockObject_GFS)
            {
                if (_GlobalFontSize != value)
                {
                    _GlobalFontSize = value;
                    NotifyStaticPropertyChanged(()=> GlobalFontSize);
                }
            }
        }
    }

    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

    public static void NotifyStaticPropertyChanged(string propertyName)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
    }

    public static void NotifyStaticPropertyChanged<T>(Expression<Func<T>> property)
    {
        var expr = property.Body as MemberExpression;
        if (expr == null)
            throw new ArgumentException("Lambda does not contain member expression. () => MyClassOrObject.Property");
        NotifyStaticPropertyChanged(expr.Member.Name);
    }
}

编辑:如果事件是在基类中定义的,则它不起作用。

public abstract class MyBaseViewModel
{
    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;

    public static void NotifyStaticPropertyChanged(string propertyName)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
    }

    public static void NotifyStaticPropertyChanged<T>(Expression<Func<T>> property)
    {
        var expr = property.Body as MemberExpression;
        if (expr == null)
            throw new ArgumentException("Lambda does not contain member expression. () => MyClassOrObject.Property");
        NotifyStaticPropertyChanged(expr.Member.Name);
    }
}

public class GlobalManager : MyBaseViewModel
{
    static object _LockObject_GFS = new object();
    static double _GlobalFontSize = 10.0;
    public static double GlobalFontSize
    {
        get
        {
            lock (_LockObject_GFS)
            {
                return _GlobalFontSize;
            }
        }
        set
        {
            lock (_LockObject_GFS)
            {
                if (_GlobalFontSize != value)
                {
                    _GlobalFontSize = value;
                    NotifyStaticPropertyChanged("GlobalFontSize");
                }
            }
        }
    }
}

StaticPropertyChangedEvent 必须定义在属性所在的同一类中,才能更新绑定:

View is not getting notified when value of static Property Changes

【讨论】:

  • If I define a property in my VM (current DataContext), and bind it to a TextBlock, it updates correctly with the current value. 这些 Get/Set-GlobalResource 方法有效。除此之外,如果我在基类中或在具有静态属性本身的类中拥有StaticPropertyChanged 事件,会有什么不同吗?
  • “如果我在基类中或在具有静态属性的类中具有 StaticPropertyChanged 事件,是否会有所不同”?是的,确实如此。
  • 奇怪但很好......我会尽量减少课程。谢谢。
  • 很奇怪,在这个问题上搜索了两天后,这个答案解决了它,尽管看了很多其他的。现在我必须弄清楚为什么这行得通而其他人没有……
猜你喜欢
  • 2020-07-22
  • 2017-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 2021-08-02
  • 1970-01-01
相关资源
最近更新 更多