DependencyProperty绑定模式twoway但propertychangedeventhandler为null

时间:2011-04-22 01:42:56

标签: c# xaml mvvm datacontext inotifypropertychanged

我正在尝试使用C#和XAML来遵循MVVM设计范例。我遇到了嵌套用户控件的问题。我正在尝试将嵌套用户控件上的元素绑定到ViewModel中的一个值(通过DataContext属性绑定到View)。相同的ViewModel用于外部和嵌套用户控件。

它部分按原样工作,但更改只从ViewModel单向转到嵌套用户控件。我需要在嵌套用户控件中进行更改以传播回ViewModel。

从主视图的XAML开始,我有:

<UserControl>

   <!-- ... -->

   <UserControl.DataContext>
      <local:MyViewModel x:Name="myViewModel" />
   </UserControl.DataContext>

   <!-- ... -->

   <local:NestedUserControl
      x:Name="nestedUserControl"
      CustomNestedValue="{Binding Path=CustomValue, ElementName=myViewModel, Mode=TwoWay}" />

</UserControl>

在ViewModel的C#代码中:

// Constructor
public MyViewModel()
{
   CustomValue = true;
}

private bool _customValue;
public bool CustomValue
{
   get { return _customValue; }
   set
   {
       if (_customValue != value)
       {
          _customValue = value;
          RaisePropertyChanged ("CustomValue");
       }
   }
}

NestedUserControl背后的代码中,我有:

public static readonly DependencyProperty CustomNestedValueProperty =
   DependencyProperty.Register (
      "CustomNestedValue",
      typeof (bool),
      typeof (NestedUserControl),
      new FrameworkPropertyMetatdata
      {
         BindsTwoWayByDefault = true,
         PropertyChangedCallback = 
            new PropertyChangedCallback (CustomNestedValueChangedCallback)
      });

public bool CustomNestedValue
{
   get { return (bool) GetValue (CustomNestedValueProperty); }
   set { SetValue (CustomNestedValueProperty, value); }
}

protected static void CustomNestedValueChangedCallback (
   DependencyObject Source,
   DependencyPropertyChangedEventArgs e)
{
   bool value = (bool) e.NewValue;
   NestedUserControl control = source as NestedUserControl;
   control.OnCustomValueChange (value);
}

public void OnCustomValueChange (bool value)
{
   RaisePropertyChanged ("CustomNestedValue");

   // Do other stuff ...
}

// This function is where the nested user control gets direct
// interactions from the user which cause the dependency
// property to change.  When this event occurs, the change needs
// to be communicated back up to the view model.
private void _onPreviewMouseDown (object sender, MouseButtonEventArgs e)
{
   CustomNestedValue = !CustomNestedValue;
}

[注意:在XAML中设置绑定时,我不仅要将绑定模式设置为TwoWay,而且还尝试将此设置为上面代码中DependencyProperty的默认行为。没有运气。]

嵌套用户控件和ViewModel代码背后的代码都包含PropertyChangedEventHandler事件/响应,这是INotifyPropertyChanged接口所必需的。据我所知,这是XAML元素和ViewModel之间的绑定保持同步的方式。

public event PropertyChangedEventHandler PropertyChanged;

protected void RaisePropertyChanged(string propertyName)
{
   try
   {
      if (this.PropertyChanged != null)
         this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
   }
   catch (Exception e)
   {
      //  ...
   }
}

运行代码时,只要为RaisePropertyChanged调用NestedUserControl函数,PropertyChanged事件始终为 null 。这只是嵌套用户控件的问题,而不是外部用户控件的问题。不应该通过绑定机制自动设置此事件吗?

我已经在这几天苦苦挣扎但现在无济于事。任何帮助将非常感激。谢谢!

1 个答案:

答案 0 :(得分:2)

绑定到DependencyObject而不使用INotifyPropertyChanged接口。实际上,如果在CustomNestedValue的{​​{1}}属性的getter或setter中设置断点,您会发现在XAML中绑定时它永远不会命中。从本质上讲,NestedUserControl是一种实现绑定而不会从INotifyPropertyChanged下降的方式。

DependencyObject绑定到MyViewModel.CustomValue时,绑定代码调用(伪代码):

NestedUserControl

NestedUserControl.SetBinding(binding, NestedUserControl.CustomNestedValueProperty) 事件从未注册,并将保持为空。但是,这并不一定能解释为什么该值不会返回到ViewModel。

无论如何,您可以删除一些移动的部分并使用

INotifyPropertyChanged.PropertyChanged

这就是我的大部分DependencyProperties的编写方式,它们支持public static readonly DependencyProperty CustomNestedValueProperty = DependencyProperty.Register("CustomNestedValue", typeof (bool), typeof (NestedUserControl), null); public bool CustomNestedValue { get { return (bool) GetValue (CustomNestedValueProperty); } set { SetValue (CustomNestedValueProperty, value); } } 绑定。