2011-04-05 3 views
3

내 ViewModel에서 사용자 클래스 인 하위 속성 "B"가있는 클래스 "A"가 있습니다. 두 클래스 모두 INotifyPropertyChanged를 구현하고 B의 PropertyChanged 이벤트는 Fire A의 PropertyChanged 이벤트 (올바른 속성 이름 "B")에 연결됩니다.WPF 4 : PropertyChanged가 바인딩을 업데이트하지 않습니다.

또한 매우 간단한 바인딩 (새 바인딩 ("A.B"))을 사용하여 코드에 B에 바인딩 된 DependencyProperty "DPB"가 내 ViewModel에 있습니다. ABC (B의 속성)

  • 1 바인딩

    • 1

    DPB

  • 에 바인딩 AB
  • 1에 직접 바인딩 :

    지금 내 뷰에있는 세 개의 텍스트 상자를 처음 실행하면 AB와 DPB 텍스트 상자 모두 올바른 값을 표시합니다. 그러나 A.B.C 텍스트 상자를 변경하면 A.B 텍스트 상자 만 업데이트되며 DPB 텍스트 상자는 업데이트되지 않습니다.

    모든 PropertyChanged 알림 코드를 통해 디버깅했으며 올바른 값으로 전달되었습니다.

    PropertyChanged 이벤트가 발생하면 DependencyProperty (또는 해당 바인딩)가 업데이트되지 않는 것 같습니다. 아무도 왜 또는 어떻게이 동작을 변경 말해 줄래?

    감사합니다.

  • +0

    당신은 바인딩에'모드 = TwoWay'를 추가해야 할 수도 있습니다. 그러나 나는 당신의 질문을 정확하게 이해하고 있는지 확신 할 수 없다. 코드를 추가 할 수 있을까? – Damascus

    +1

    클래스 구조를 조금 만들고 여기에 코드를 붙여 넣으면 훨씬 나아질 것입니다 ... –

    답변

    3

    나는 당신에게 나쁜 소식이 있습니다.

    내부 DependencyObject.SetValue 새 값이 이전 값과 같은지 확인하는 검사가 있습니다. 따라서 A.B에 바인딩되어 있고 A.B.C을 변경하면 A.B의 PropertyChanged 이벤트가 발생하므로 Binding mechanizm이이 이벤트를 처리하고 DependencyObject.SetValue을 호출합니다. 그러나 이전 및 신규 A.B 값의 동일성으로 인해 DP에는 변경 사항이 적용되지 않습니다.

    올바른 DP 실행을 수행하려면 A.B의 새 인스턴스를 만들어야합니다.이 인스턴스는 큰 두통으로 끝납니다.

    업데이트]

    당신은 그것의 속성이 변경 될 때 변경되었음을 알림을 지원하여 Freezable 개체를 사용할 수 있습니다. DependencyObject는 Freezables와 올바르게 작동하므로 다음 예제는 필요한 작업을 수행합니다.

    모델 클래스 :

    public class A 
    { 
        public A() 
        { 
         this.B = new B(); 
        } 
        public B B 
        { 
         get; private set; 
        } 
    } 
    
    public class B : Freezable, INotifyPropertyChanged 
    { 
        protected override Freezable CreateInstanceCore() 
        { 
         return new B(); 
        } 
    
        private string _c = "initial string"; 
        public string C 
        { 
         get 
         { 
          return _c; 
         } 
         set 
         { 
          this._c = value; 
          this.OnPropertyChanged("C"); 
          this.OnChanged(); 
         } 
        } 
    
        public event PropertyChangedEventHandler PropertyChanged; 
    
        protected void OnPropertyChanged(string name) 
        { 
         var safe = this.PropertyChanged; 
         if (safe != null) 
         { 
          safe(this, new PropertyChangedEventArgs(name)); 
         } 
        } 
    } 
    

    XAML :

    <StackPanel> 
        <TextBox Text="{Binding A.B.C}" /> 
        <TextBox Text="{Binding MyProperty.C}" /> 
        <Button Click="Button_Click"/> 
    </StackPanel> 
    

    코드 숨김

    public partial class TextBoxesView : UserControl 
    { 
        public TextBoxesView() 
        { 
         InitializeComponent(); 
    
         this.A = new A(); 
         this.DataContext = this; 
    
         BindingOperations.SetBinding(this, TextBoxesView.MyPropertyProperty, new Binding("A.B")); 
        } 
    
        private void Button_Click(object sender, RoutedEventArgs e) 
        { 
         this.A.B.C = DateTime.Now.ToString(); 
        } 
    
        public A A 
        { 
         get; 
         private set; 
        } 
    
        public B MyProperty 
        { 
         get 
         { 
          return (B)this.GetValue(TextBoxesView.MyPropertyProperty); 
         } 
         set 
         { 
          this.SetValue(TextBoxesView.MyPropertyProperty, value); 
         } 
        } 
    
        public static readonly DependencyProperty MyPropertyProperty = 
         DependencyProperty.Register("MyProperty", 
          typeof(B), 
          typeof(TextBoxesView), 
          new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, (d, e) => { })); 
    } 
    
    +0

    흠, 나는 두려웠습니다. 평등성 점검이 어떻게 수행되는지 알고 있습니까? 만약 equals 메소드와 gethash 메소드를 오버라이드한다면, 업데이트 할 수 있을까요? –

    +1

    개체가 동일하기 때문에 같음/GetHash 메서드는 도움이되지 않습니다. 사실 저는 당신의 목적을 모릅니다. 나는 당신에게 조언 할 수 없습니다. 내가 너라면, 나는 그 같은 문제가 나쁜 디자인 때문에 발생했다고 생각할 것이다. 또한 Freezable을 사용해 볼 수도 있습니다. 내 답변에 몇 가지 설명 코드를 추가했습니다. –

    +0

    도움을 주셔서 감사합니다. 특히 Freezable 제안에 대해 지금 살펴보고 있습니다. 나는 그것이 다소 디자인 문제라고 동의하지만, B 클래스 유형이 디자인 타임에 알려져 있지 않은 곳에서 사용되고 있기 때문에 중간 속성의 필요성이있다. 귀하의 도움에 감사 드리며 곧 답변 할 것입니다. –

    관련 문제