1

我有一个 AdvanceBasicEffect 类,它有一个属性 SpecularColor,它是 AdvanceVector3 类的对象,所以当我绑定 specularColor.X 属性时,属性更改事件会触发,但仅在 AdvanceVector3 类中,而不在 AdvanceBasicEffect 中。

查看您将弄清楚的代码:

public partial class Lights : UserControl
{
    public Lights()
    {
        InitializeComponent();

        this.DataContext = this;
        basicEffect = new AdvanceBasicEffect();
    }

    public AdvanceBasicEffect basicEffect { get; set; }
}

public class AdvanceBasicEffect : INotifyPropertyChanged
{
    public AdvanceBasicEffect()
    {
        SpecularColor = new AdvanceVector3();
        basicEffect = ((bathroom)CurrentWindowHandle.currentGame.Components.First()).basicEffect;
    }

    BasicEffect basicEffect;

    AdvanceVector3 _SpecularColor;
    public AdvanceVector3 SpecularColor 
    { 
        get
        {
            return _SpecularColor;
        }
        set
        {
            //Line 1 : event not occuring 

            _SpecularColor = value;
            if(basicEffect!=null)
             basicEffect.DirectionalLight0.Direction = new Vector3(_SpecularColor.X, _SpecularColor.Y, _SpecularColor.Z);
            valueChanged("SpecularColor");

        }
    }

    private void valueChanged(string p)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(p));
            CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_80", basicEffect, false);
            CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_111", basicEffect, false);
            CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_112", basicEffect, false);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}



public class AdvanceVector3 : INotifyPropertyChanged
{
    float _X;
    public float X
    {
        get
        {
            return _X;
        }
        set
        {
            _X = value;
            valueChanged("X");
        }
    }

    float _Y;
    public float Y
    {
        get
        {
            return _Y;
        }
        set
        {
            _Y = value;
            valueChanged("Y");
        }
    }

    float _Z;
    public float Z
    {
        get
        {
            return _Z;
        }
        set
        {
            _Z = value;
            valueChanged("Z");
        }
    }

    private void valueChanged(string p)
    {
        //line 2 :Event Occuring 
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(p));
            //CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_80", basicEffect, false);
            //CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_111", basicEffect, false);
            //CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_112", basicEffect, false);
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

在评论“第 1 行”事件发生,而在“第 2 行”事件发生,所以我的问题是当子属性发生变化时,为什么父属性没有发生变化。我不能在同一个类中定义 X、Y、Z,因为我有许多需要 AdvanceVector3 类的属性

绑定代码如下:

  <Slider ToolTip="SpecularColorX" Minimum="-1" Maximum="1" Value="{Binding basicEffect.SpecularColor.X}" />
        <Slider ToolTip="SpecularColorY" Minimum="-1" Maximum="1" Value="{Binding basicEffect.SpecularColor.Y}" />
        <Slider ToolTip="SpecularColorZ" Minimum="-1" Maximum="1" Value="{Binding basicEffect.SpecularColor.Z}" />
4

2 回答 2

4

如果我正确地回答了您的问题,我认为您误解了 INPC 的含义以及何时触发。

如果你说有

Class ParentClass : INotifyPropertyChanged {

  public ChildClass SomeObject {
    get { ... }
    set { ... valueChanged("SomeObject"); }
  }

  ...

}

Class ChildClass : INotifyPropertyChanged {

  public string SomeString {
    get { ... }
    set { ... valueChanged("SomeString"); }
  }

  ...

}

现在,如果您从 xaml 或代码隐藏更改SomeString对象ParentClass

var parentObject = new ParentClass {SomeObject = new ChildClass {SomeString = "Hi"}};

// will trigger property changed in ChildClass for SomeString property
// however it will not trigger a PropertyChanged in ParentClass for SomeObject
parentObject.SomeObject.SomeString = "New String"

// will trigger property changed in ParentClass for SomeObject property
parentObject.SomeObject = new ChildClass();

您的 xaml 绑定工作正常,因为您直接绑定到属性,并且当它们更改时,您的视图会相应更新。

如果您想SomeString从 内部“观察”任何更改ParentClass,那么您需要订阅PropertyChangedChildClass.SomeString

所以说ParentClass可以更新为

  public ChildClass SomeObject {
    get { ... }
    set { 
       if (value == _someObject)
         return;

       _someObject.PropertyChanged -= ChildObjectValueChanged;
       _someObject = value;
       _someObject.PropertyChanged += ChildObjectValueChanged;

       valueChanged("SomeObject"); }
  }

  private void ChildObjectValueChanged(object sender, PropertyChangedEventArgs args) {
    if (args.PropertyName == "SomeString")
      // Child Object property "SomeString" has changed. Do what you need here
  }
于 2013-06-22T10:52:36.983 回答
0

你的二传手永远不会被调用。Wpf 本身调用PropertyChagned实现INotifyPropertyChanged。您应该做的是在您的AdvancedBasicEffect类构造函数中自己订阅更改的事件,而不是在方法中设置网格效果valueChanged

public AdvanceBasicEffect()
{
    SpecularColor = new AdvanceVector3();
    basicEffect = ((bathroom)CurrentWindowHandle.currentGame.Components.First()).basicEffect;

    SpecularColor.PropertyChanged += (o,e) => 
    {
        CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_80", basicEffect, false);
        CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_111", basicEffect, false);
        CurrentWindowHandle.currentGame.models[0].SetMeshEffect("Archinteriors7_10_112", basicEffect, false);
    }
}
于 2013-06-22T10:27:20.470 回答