1

クラス AdvanceBasicEffect があり、クラス AdvanceVector3 クラスのオブジェクトであるプロパティ SpecularColor があるため、specularColor.X プロパティをバインドすると、プロパティ変更イベントが発生しますが、AdvanceBasicEffect ではなく AdvanceVector3 クラスでのみ発生します。

あなたが理解するコードを見てください:

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;
}

コメントで「Line 1」イベントが発生しているのに対し、「Line 2」イベントでは発生しているため、サブプロパティが変更されたときに親プロパティの変更が発生しないのはなぜですか。AdvanceVector3 クラスを必要とする多くのプロパティがあるため、同じクラスで X、Y、Z を定義できません。

バインディング コードは次のとおりです。

  <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 に答える