【问题标题】:Two way binding ignores source changes两种方式绑定忽略源更改
【发布时间】:2014-06-26 12:02:30
【问题描述】:

我有一个带有依赖属性的自定义控件,并且绑定到ViewModel 属性只能像OneWayToSource 一样工作。我搞砸了什么?

绑定

<local:MyControl SelectedItem="{Binding SelectedPage}"/>

ViewModel 和控件

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ViewModelPageBase _selectedPage;
    public ViewModelPageBase SelectedPage
    {
        get { return _selectedPage; }
        set
        {
            _selectedPage = value;
            OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string property = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
}

public class MyControl : ContentControl
{
    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set
        {
            // never get here
            SetValue(SelectedItemProperty, value);
        }
    }
    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
        "SelectedItem",
        typeof(object),
        typeof(MyControl),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
}

之前我使用ItemsControl,绑定是双向工作的。现在,使用MyControl,只有当SelectedItem 被更改时,SelectedPage 才会更新。其他方式(在某处设置SelectedPage)不会更新SelectedItem

想法?

【问题讨论】:

  • 什么是 OnPropertyChanged();方法?显示它。
  • 它适用于其他属性,但可以肯定。此示例已简化,仅包含相关部分(我希望如此)。
  • 据我了解,您是通过堆栈帧获取 PropertyChangedEventArgs 的属性名称的,不是吗?
  • @EugenePodskal,是的,4.5 的东西。我已经尝试像字符串一样指定它,仍然有问题。
  • 是的,他完全正确。 Binding 引擎从不设置 CLR 属性,它总是更改基础 DependencyProperty。 Style Setter、Tigger 或 Animation 也是如此。

标签: c# wpf mvvm binding


【解决方案1】:

我看到你对依赖属性设置器的评论:

公共对象 SelectedItem { 获取{返回(对象)GetValue(SelectedItemProperty); } 放 { //永远不会到这里 SetValue(SelectedItemProperty, 值); } }

我想你已经知道了,但是如果你没有在 Dependency Property 中调用 setter,如果你想收到任何更改的通知,你应该在 FrameworkPropertyMetadata 的第三个参数中添加一个 PropertyChangedCallback

Setters not run on Dependency Properties?

【讨论】:

  • 当我制作依赖属性时,那么我必须使用callback来更新它以进行双向绑定吗?它与msdn 不匹配:TwoWay 绑定导致对源属性或目标属性的更改自动更新另一个。我正在调用回调,但属性未更新(通过设置器)。还是他们的意思是 static 属性得到更新?而且我必须使用回调来更新控件属性?听起来很愚蠢,看起来像是额外的工作。
  • 属性会被设置,但是如果你在setter中设置了一个断点,它就不会被调用。我不知道你的其余代码,所以我希望你不要通过断点来验证绑定。
  • 我对您的最后陈述感到非常困惑。 如何在不调用 setter 的情况下设置属性???
  • 其实,我现在明白你的意思了。哈哈。谢谢!
  • 查看我的链接“Setters not run on Dependency Properties?” ,答案在:WPF绑定引擎直接调用GetValue和SetValue(绕过属性setter和getter)。您需要该属性存在,以便 XAML 标记支持它(并正确编译)。
【解决方案2】:

在 selectedItem Dependancyproperty 声明中,

public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
        "SelectedItem",
        typeof(object),
        typeof(ViewNavigatorControl),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));



typeof(ViewNavigatorControl) should be replaced by typeof(MyControl)

让我知道这是否能解决问题

【讨论】:

  • 这是ViewNavigatorControl 的删减,我尝试只放重要部分,但在将其重命名为MyControl 时确实出错了>
  • 好的,发布您尝试绑定属性的 XAML 代码
【解决方案3】:

我看到两个问题:

首先你忘了关闭}

SelectedItem="{Binding SelectedPage}"

其次,在您的依赖属性上,第三个对象应该是您的所有者类。在您的情况下 MyControl

public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(
     "SelectedItem",
     typeof(object),
     typeof(**ViewNavigatorControl**),
     new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

但也许这个错误只是一个糟糕的复制/粘贴。

【讨论】:

  • 感谢您发现代码中的错误,这只是由于这里更改了代码,同时试图减少代码量。现在将修复它们。问题仍然存在。
猜你喜欢
  • 2016-10-23
  • 2016-02-27
  • 2017-09-05
  • 2014-02-13
  • 1970-01-01
  • 2017-01-03
  • 2018-12-09
  • 2012-01-14
  • 2017-11-18
相关资源
最近更新 更多