强制重新评估依赖属性以强制值

Posted

技术标签:

【中文标题】强制重新评估依赖属性以强制值【英文标题】:Force reevaluation of dependency property to coerce value 【发布时间】:2020-10-14 22:36:32 【问题描述】:

我看到这个blog post 有这个代码:

        Person p = new Person("Methuselah");

        p.Age = 28;
        p.SuperOld = true;    // Age coerced to 999

        p.Age = 56;           // Age still 999
        p.SuperOld = false;   // Age now becomes 56

我有一个非常相似的情况:当我更改一个属性(在此示例中为 SuperOld)时,另一个属性(Age)的值应该被强制转换为另一个值(999)。当我重置第一个属性 (SuperOld) 时,第二个应该获得同时设置的 baseValue (56)。

但我不知道当第一个属性改变时我应该如何强制第二个属性。

任何提示将不胜感激。

【问题讨论】:

【参考方案1】:

我会创建一个支持字段并让属性 getter 评估另一个属性:


    private int _age;
    public int Age
    
        get => SuperOld ? 999 : _age;
        set => _age = value;
    

    public bool SuperOld  get; set; 

【讨论】:

现在图像它必须是一个依赖属性。例如用于绑定目的【参考方案2】:

好吧,如果您想在SuperOld 更改时强制Age 属性,请调用CoerceValue。您可以在microsoft docs 上阅读更多相关信息。关键信息是,此方法使用“baseValue”调用您的 CoerceValueCallback,在您的情况下为 56

这是一个最小的工作示例:

    public class Person : DependencyObject
    
        public static readonly DependencyProperty AgeProperty = DependencyProperty.Register(
            "Age",
            typeof(int),
            typeof(Person),
            new PropertyMetadata(default(int), AgeChanged, CoerceAge));

        public static readonly DependencyProperty IsSuperOldProperty = DependencyProperty.Register(
            "IsSuperOld",
            typeof(bool),
            typeof(Person),
            new PropertyMetadata(default(bool), IsSuperOldChanged));

        public int Age
        
            get => (int)GetValue(AgeProperty);
            set => SetValue(AgeProperty, value);
        

        public bool IsSuperOld
        
            get => (bool)GetValue(IsSuperOldProperty);
            set => SetValue(IsSuperOldProperty, value);
        

        private static void AgeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        
        

        private static object CoerceAge(DependencyObject d, object basevalue)
        
            var person = (Person)d;
            if (person.IsSuperOld)
            
                return 999;
            

            return basevalue;
        

        private static void IsSuperOldChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        
            d.CoerceValue(AgeProperty);
        
    

这是 NUnit 测试:

    [Test]
    public void Should_work_like_in_blog()
    
        Person p = new Person();

        p.Age = 28;
        p.IsSuperOld = true;    // Age coerced to 999

        Assert.That(p.Age, Is.EqualTo(999));

        p.Age = 56;           // Age still 999
        p.IsSuperOld = false;   // Age now becomes 56

        Assert.That(p.Age, Is.EqualTo(56));
    

【讨论】:

以上是关于强制重新评估依赖属性以强制值的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 - 如何仅在某些情况下强制执行对象属性(构建器模式,依赖注入)

依赖属性

WPF - 如何强制命令通过其 CommandBindings 重新评估“CanExecute”

WPF的依赖项属性

Linux 强制安装 rpm 包

WPF入门教程系列十四——依赖属性