MVVM UserControl绑定未被推回到父控件

时间:2011-10-01 03:05:38

标签: c# wpf data-binding mvvm

我正在制作一个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中,它有一个名为DatePickerViewModel的子EndDate,它绑定到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.dllat codeplex)。

1 个答案:

答案 0 :(得分:1)

唯一有意义的事情(基于所显示的代码)是(1)ViewModelBase不实现INotifyPropertyChanged或(2)您的DatePickerView控件在依赖性Properies上做错了。

我建议发布一个完整的repro,包括DataPickerView和ViewModelBase。

修改

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

您的下拉列表会更改EndDate / DatePickerViewModel的属性,但请记住,更改其属性(Date,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;
    }
  }
}