c# - DependencyProperty 绑定(bind)模式双向但 propertychangedeventhandler 为空

标签 c# xaml mvvm datacontext inotifypropertychanged

我正在尝试使用 C# 和 XAML 遵循 MVVM 设计范例。我遇到了嵌套用户控件的问题。我正在尝试将嵌套用户控件上的元素绑定(bind)到 ViewModel 中的一个值(通过 DataContext 属性绑定(bind)到 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 中设置绑定(bind)时,我不仅将绑定(bind)模式设置为 TwoWay,而且我试图在上面的代码中将此设置为 DependencyProperty 的默认行为。没运气。]

嵌套用户控件的代码和 ViewModel 代码都包含以下 PropertyChangedEventHandler事件/响应,这是 INotifyPropertyChanged 所必需的界面。据我了解,这就是 XAML 元素和 ViewModel 之间的绑定(bind)如何保持同步。
public event PropertyChangedEventHandler PropertyChanged;

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

当我运行代码时,只要 RaisePropertyChangedNestedUserControl 调用函数, PropertyChanged事件总是 .这只是嵌套用户控件的问题,而不是外部用户控件的问题。这个事件不应该通过绑定(bind)机制自动设置吗?

我已经为此苦苦挣扎了几天,但无济于事。任何帮助将非常感激。谢谢!

最佳答案

绑定(bind)到 DependencyObject在不使用 INotifyPropertyChanged 的情况下运行界面。事实上,如果你在 CustomNestedValue 的 getter 或 setter 中设置断点NestedUserControl 的属性(property),你会发现在 XAML 中绑定(bind)时它永远不会命中。本质上,INotifyPropertyChanged是一种无需从 DependencyObject 下降即可实现绑定(bind)的方法.

MyViewModel.CustomValue绑定(bind)到 NestedUserControl ,绑定(bind)代码调用(在伪代码中):

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

无论如何,您可以移除一些移动部件并使用
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); }
}

这就是我的大部分 DependencyProperties 的编写方式,它们确实支持 TwoWay捆绑。

关于c# - DependencyProperty 绑定(bind)模式双向但 propertychangedeventhandler 为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5751535/

相关文章:

c# - 从 xamarin 将长视频上传到 Web API 服务器

c# - 我应该如何使用 Rx + DynamicData 定期检查许多在线服务的更新?

c# - 如何从代码后面访问数据到 MVVM

c# - 进度条的 Visibility 属性在运行时不会改变

wpf - 使用 Expression Blend 和 Visual Studio 时,如何为设计人员 stub 数据?

wpf - 摆脱文本框验证边框

wpf - 使用 mvvm 的可编辑 ComboBox 设置插入符位置

c# - Xamarin Forms MVVM 与实际模型

wpf - 在 XAML : Stop an Event from Taking Place

c# - 如何通过 .NET 在 MongoDB 中创建索引