代码之家  ›  专栏  ›  技术社区  ›  Victor

wpf propertychange不层叠-设置一个自定义类的动画DependencyProperty更改其他属性-propertychange只为第一个激发

  •  0
  • Victor  · 技术社区  · 15 年前

    非常简单,这是我的问题:(底部的解决方案)

    我有一个自定义类,继承Animatable和InotifyPropertyChange,其中包含一个DependencyProperty(我将其设置为动画,例如从1到10)和一个额外的属性(我希望使用带有绑定的XAML):

    MyClass : Animatable, INotifyPropertyChanged {
    
        public static DependencyProperty AnimateValueProperty = DependencyProperty.Register(
          "AnimateValue",
          typeof(double),
          typeof(MyClass)
         );
    
        public double AnimateValue {
            get { return (double)GetValue(AnimateValueProperty); }
            set {
                    SetValue(AnimateValueProperty, value);
                    OnPropertyChanged(new PropertyChangedEventArgs("AnimateValue"));
                    OnPropertyChanged(new PropertyChangedEventArgs("GuiValue")); //Added in edit
                }
            }
        }
    
        public double GuiValue {
            get { 
                return AnimateValue + 10; 
                //More fancy stuff happening in the real class...
            }
        }
    
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
            if (PropertyChanged != null) {
                PropertyChanged(this, e);
            }
        }
    
        protected override Freezable CreateInstanceCore() {
            return new MyClass();
        }
    }
    

    当我将gui元素绑定到我实际动画的属性(animatevalue)时,一切都按预期工作——当我将gui元素绑定到相关属性(guivalue)时,什么都不会发生。我想改变的事件不会到达那个属性,但我真的不知道如何解决这个问题。有什么指针吗?

    非常感谢您的帮助!

    编辑:感谢Adam Sills和Kai Wang的两个回复,我真蠢,竟然漏掉了第二个onPropertyChange调用,不过我以前试过,但没用。为了进行调试,我在animateValue.set函数中放置了一个writeline,然后发现-它根本不会被执行!

    我还试着换了盖特,让他永远回20分-不换!:-o似乎动画完全跳过了属性get和set,并对底层DependencyProperty进行了动画和读取…还是我误解了?我使用的动画代码是:

    DoubleAnimation da = new DoubleAnimation (1, 10, new Duration(TimeSpan.FromSeconds(3)));
    myClassInstance.BeginAnimation(MyClass.AnimateValueProperty, da);
    

    隐马尔可夫模型。。。在这里编写代码之后,不使用setter似乎非常合理(尽管我真的希望如此!)-但是,基本问题仍然存在,我仍然不明白为什么不使用吸气剂!

    编辑2: 解决方案!

    正如下面所建议的,对于连接到DependencyProperty的属性,我不能使用inotifyPropertyChange-动画和XAML在内部使用DependencyProperty,根本不使用getter和setter。

    因此-propertychangedcallback在更改时通知其他人,强制EvalueCallback返回“修复”数据。也可以验证数据,所有这些都在DependencyProperty构造函数中完成。谢谢大家!

    谢谢!

    胜利者

    4 回复  |  直到 11 年前
        1
  •  2
  •   Eric Smekens    11 年前

    下面是一个属性已更改的NotiAction模式,用于依赖项属性

      public Boolean PasswordBoxVisible {
         get { return (Boolean)GetValue(PasswordBoxVisibleProperty); }
         set { SetValue(PasswordBoxVisibleProperty, value); }
      }
    
      public static readonly DependencyProperty PasswordBoxVisibleProperty =
          DependencyProperty.Register("PasswordBoxVisible", typeof(Boolean), typeof(UserControl), new UIPropertyMetadata(false, new PropertyChangedCallback(PropChanged)));
    
      //this method is called when the dp is changed
      static void PropChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
           UserControl userControl = o as UserControl;
           //now you can use this to call some methods, raise other value changed etc, in this case OtherProperty.
           userControl.NotifyPropertyChanged("OtherProperty");
      }
    

    我有一种感觉,但并不完全确定,你可能需要做的是强迫其他价值观。 have a look at the coerce value callback section in this article

        2
  •  2
  •   Adam Sills    15 年前

    通过设置animateValue的值,可以告诉WPF它已经更改。但您永远不会告诉WPF guiValue已经更改。WPF数据绑定框架应该如何知道,当您不告诉它时,guiValue发生了变化?

    更新animateValue并发出更改通知时(由于它是依赖属性,因此不必发出更改通知),还需要发出有关guiValue的通知,因为guiValue依赖于animateValue,但在属性内手动计算。

    基本上只是增加

    OnPropertyChanged(new PropertyChangedEventArgs("GuiValue"));
    

    到animateValue设置块。

    更新:

    根据您的新编辑,如果通过XAML进行属性设置,则从不调用依赖项属性的getter/setter,而是直接通过getvalue/setvalue完成。

    如果需要对更改进行本地响应,请重写OnPropertyChanged或在DependencyProperty中提供更改回调。注册

        3
  •  1
  •   treehouse    15 年前

    我不确定我是否明白你的意思。但看看这是否有帮助。

        public double AnimateValue {
        get { return (double)GetValue(AnimateValueProperty); }
        set {
                SetValue(AnimateValueProperty, value);
                OnPropertyChanged(new PropertyChangedEventArgs("AnimateValue"));
                OnPropertyChanged(new PropertyChangedEventArgs("GuiValue "));
            }
        }
    }
    
        4
  •  1
  •   Akash Kava    15 年前

    如果您的对象是从依赖对象派生的,则不能使用inotifyPropertyChanged,因为绑定体系结构将仅使用依赖属性重新注册来使用绑定。

    为了这个你需要 只读依赖项属性 我解释如下。

    public static DependencyProperty AnimateValueProperty = 
       DependencyProperty.Register(
          "AnimateValue",
          typeof(double),
          typeof(MyClass)
       );
    
     // This is for the Readonly GuiValueKey property
     public static DependencyPropertyKey GuiValueKey = 
         DependencyProperty.RegisterReadOnly (
         "GuiValue",
          typeof(double),
          typeof(MyClass),
          new UIPropertyMetadata(0.0)
    );
    
    public double AnimateValue {
        get { return (double)GetValue(AnimateValueProperty); }
        set {
                SetValue(AnimateValueProperty, value);
                // Following statement update GuiValue wherever it
                // is binded
                this.SetValue(GuiValueKey,value + 10);
            }
        }
    }
    
    // you dont even need following line...
    // but its good to have it..
    public double GuiValue {
        get { 
            return (double)this.GetValue(GuiValueKey); 
        }
    }