【问题标题】:MVVM UserControl binding not getting pushed back to parent controlMVVM UserControl 绑定没有被推回父控件
【发布时间】:2011-10-01 03:05:37
【问题描述】:

我正在制作一个 WPF 应用程序,我有一个用于数据编辑的 UserControl,里面还有几个 UserControls(超级简化版):

<UserControl x:Name="ParentControlView">
    <DockPanel>
        <!-- other various controls, textblocks, etc. -->
        <Controls:DatePickerView DataContext="{Binding Path=EndDate, Mode=TwoWay}" />
        <!-- other various controls, textblocks, etc. -->
    </DockPanel>
</UserControl>

在父控件的 ViewModel 中,它有一个名为 EndDate 的子 DatePickerViewModel,它绑定到 DatePickerView 控件:

public class ParentControlViewModel : ViewModelBase
{
    private DatePickerViewModel _endDate;

    public DatePickerViewModel EndDate
    {
        get { return _endDate; }
        set
        {
            _endDate = value;
            RaisePropertyChanged(() => EndDate);
            RaisePropertyChanged(() => SomeProperty);
        }
    }
}

DatePickerView 控件是一些绑定到DatePickerViewModel 中的属性的组合框,没什么特别的。

当我运行我的应用程序时,DatePickerView 被正确初始化并设置为当前值,就像它应该的那样。 所以get 方法工作正常。 但是当我更改DatePickerView 上的控件并且它的 ViewModel 得到更新时,绑定到父视图的值不会在父视图中设置模型(即set 方法永远不会运行)。

显然我错过了某种数据绑定连接,但对于我的一生,我无法弄清楚那是什么,我已经搜索了所有内容,但一无所获。

更新

Minimal working sample。包括我正在使用的大部分专有日期类,可能还有一些糟糕的 MVVM 实现。我还是 MVVM 的新手。我删掉了很多不必要的代码,所以日期选择器不能正常工作,但它可以满足这个问题的目的。

您需要获取并引用MvvmFoundation.Wpf.dll (at codeplex)。

【问题讨论】:

    标签: c# wpf data-binding mvvm


    【解决方案1】:

    唯一有意义的事情(仅基于显示的代码)是 (1) ViewModelBase 没有实现 INotifyPropertyChanged 或 (2) 您的 DatePickerView 控件对 Dependency Properies 执行了错误。

    我建议发布完整的复制品,包括 DataPickerView 和 ViewModelBase。

    编辑

    好的,看一下,看看问题所在。你的 setter 永远不会被调用的原因是你的 EndDate (DatePickerViewModel) 永远不会改变。这听起来有些不言而喻,但这是底线——没有代码可以完全替换 EndDate 属性,这会导致 setter 代码运行。

    您的下拉列表会更改 EndDate/DatePickerViewModel 的属性,但请记住,更改其属性(日期、SelectedYear 等)不会设置 实例 DatePickerViewModel,这意味着setter代码不会运行。

    由于这是一个精简版本,我有点猜测您最终想要实现的目标,但我认为您想要的是在 DatePickerViewModel(可能是 DateTime 类型)上创建一个可以绑定到的 DependencyProperty并且可以在控件内的日期发生变化时通知。

    作为一种快速解决方法,添加以下代码以触发 setter 代码。请注意,这不是推荐的解决方案 - 它会导致您的父母和孩子相互引用,这(至少)很奇怪:

    //in ParentControlViewModel, change your EndDate to:
    public DatePickerViewModel EndDate
    {
      get { return _endDate; }
      set
      {
        _endDate = value;
        if (_endDate.ParentControlViewModel == null)
        {
        _endDate.ParentControlViewModel = this;
        }
        RaisePropertyChanged(() => EndDate);
      }
    }
    
    //Add to DatePickerViewModel
    public ParentControlViewModel ParentControlViewModel { get; set; }
    
    //Change Date property in DatePickerViewModel to:
    public GDate Date
    {
      get { return _date; }
      set
      {
        _date = value;
        RaisePropertyChanged(() => Date);
        if (ParentControlViewModel != null)
        {
          ParentControlViewModel.EndDate = this;
        }
      }
    }
    

    【讨论】:

    • ViewModelBase 确实实现了 INotifyPropertyChanged。我会看看我是否可以得到一个最小的工作示例。
    • 添加了任何人都可以尝试的示例。
    • 嗯...快速修复可能不起作用,因为我在几个不同的视图上使用日期选择器。依赖属性的东西现在对我来说是零意义,但我会看看我是否可以一起破解它。
    • 是的,请阅读 DP,如果您遇到困难,请发布一个新问题。我很确定这就是你想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    相关资源
    最近更新 更多