【问题标题】:Updating source using DependencyProperty in custom usercontrol在自定义用户控件中使用 DependencyProperty 更新源
【发布时间】:2012-07-23 12:09:13
【问题描述】:

当自定义 UserControl 的目标 DependencyProperty 更改时,绑定源未更新。

源是一个用 MEF 加载到我的自定义 UserControl 的 DataContext 中的 ViewModel。

我的绑定在 MyUserControl 的根 XAML 中如下所示

// MyUserControl.xaml
<MyUserControlBase x:Class="MyUserControl" MyDependencyProperty="{Binding ViewModelProperty}">

如果我将 MyDependencyProperty 与 FrameworkPropertyMetadata 一起使用并在属性更改时使用回调函数,我可以执行以下操作,效果很好

// MyUserControlBase.cs
private static void MyDependencyProperty_Changed(DependencyObject depObj, DependencyPropertyChangedEventArgs args)
{
    var filter = (UserControl )depObj;
    var vm = (ViewModel)filter.DataContext;
    vm.ViewModelProperty= (VMPropType)args.NewValue;
}

在继承 UserControl 的 MyUserControlBase 中注册 DependencyProperty。

// MyUserControlBase.cs
public static readonly DependencyProperty MyDependencyPropertyProperty = DependencyProperty.Register("MyDependencyProperty",
            typeof(VMPropType),
            typeof(MyUserControlBase),
            new FrameworkPropertyMetadata(null, MyDependencyProperty_Changed));

但是为什么我不能在 XAML 中完成简单的双向绑定工作?

输出窗口显示没有绑定失败。我可以看到正在调用 ViewModel.ViewModelProperty getter。一旦 MyDependencyProperty 发生变化,就不是 setter。

这似乎不是事件顺序的问题。 ViewModel 是在 DependencyProperty 第一次更改之前创建的。

我也看过Setting up binding to a custom DependencyProperty inside a WPF user control 但他的问题似乎略有不同,因为我实际上是从我自己的持有 DependencyProperty 的 Base 类继承而来的。

感谢您的帮助。

编辑:带有示例解决方案的链接。 Solution zip here

抱歉,链接看起来很吓人,我不知道很多快速文件共享网站。如果它的评论不好,我会尽快删除它,但它似乎没问题。

【问题讨论】:

  • 请在您注册依赖属性的地方发布代码。

标签: wpf user-controls dependency-properties


【解决方案1】:

答案已更新/无关信息已删除

查看示例中的代码后,我发现了问题所在。你有这个“选择器”控件。在BindDependencies 方法中,您在MyControlBase.MyDependencyProperty 上设置绑定。但同时您也将此属性绑定到控件的数据上下文(在MyUserControl.xaml 中)。实际上,这意味着在BindDependencies 方法中,您正在覆盖 到您的视图模型的绑定,因此在该方法之后它不活动 - 您可以通过在SetBinding 调用之前和之后自己看到这一点并调用BindingOperations.GetBindingExpression(control, MyUserControlBase.MyPropertyDependencyProperty) - 绑定不同。这就是您的代码不起作用的原因。我想你将不得不找到另一种在那里转移价值的方式:)

一些附加信息

在 WPF 中,一个属性只能是一个绑定的目标。这实际上是非常合乎逻辑的——如果一个属性绑定到两个源——它应该使用哪一个?在这种情况下,绑定被标记为OneWayToSource这一事实并不重要,因为它仍然算作以控件属性为目标的绑定。

您可以调查并查看它是否适合您的一种方法是MultiBinding - 它确实允许通过实现您自己的IMultiValueConverter 将控件的属性绑定到多个源。您可以在 MSDN 上提供的链接中找到更多信息。

【讨论】:

    【解决方案2】:

    您是否将 ViewModelProperty 公开为常规属性..

    通常你会执行以下操作....

    public static readonly DependencyProperty ViewModelPropertyProperty = DependencyProperty.Register("ViewModelProperty", 
                typeof(VMPropType), 
                typeof(MyUserControlBase), 
                new FrameworkPropertyMetadata(null, ViewModelProperty_Changed)); 
    
    public VMPropType ViewModelProperty {
        get { return (VMPropType)GetValue(ViewModelPropertyProperty); }
        set { SetValue(ViewModelPropertyProperty,value); }
    }
    

    编辑——评论后。

    您何时检查属性是否已更改?默认情况下,WPF 绑定仅在失去焦点时更新值,您可以更改绑定的 UpdateSourceTrigger 属性以更改此行为。

    【讨论】:

    • 在 MyUserControlBase_Changed 方法中,这是来自 DependencyProperty 的 Register 方法的回调。 DependencyPropertyChangedEventArgs.NewValue 看起来是正确的。它只是不更新​​我的 XAML 绑定源。我已经尝试过 UpdateSourceTrigger=PropertyChanged。
    • 您能否在 ViewModelProperty 的实际设置器中添加检查。可能是您检查得太早,而更改尚未级联。
    • 我已经这样做了,但是只有当我执行“new MyUserControl()”并且 MEF 创建 ViewModel 时它才会被击中。我得到一个返回 null 的两个 get 和一个分配 null 的 set。之后我在 MyUserControlBase.MyDependencyProperty_Changed 上看到了一个 proc,其中 args 包含正确的值。但我的 ViewModel 中没有任何变化。
    猜你喜欢
    • 2013-05-04
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    相关资源
    最近更新 更多