MVVM UserControl绑定没有被推回父控件

本文关键字:控件 UserControl 绑定 MVVM | 更新日期: 2023-09-27 18:10:15

我正在制作一个WPF应用程序,我有一个UserControl用于数据编辑,其中有几个UserControl(超简化版本):

<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方法永远不会运行)。

显然,我错过了某种类型的数据连接连接,但对于我的生活,我不能弄清楚那是什么,我已经到处搜索,一无所获。

更新

最小工作样本。包括我正在使用的大多数专有日期类,可能还有一些糟糕的MVVM实现。我还是MVVM的新手。我去掉了很多不必要的代码,所以日期选择器不能很好地工作,但它做了这个问题需要做的事情。

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

MVVM UserControl绑定没有被推回父控件

唯一有意义的事情(基于所示的代码)是(1)ViewModelBase不实现INotifyPropertyChanged或(2)你的DatePickerView控件正在做一些错误的依赖属性。

我建议发布一个完整的报告,包括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;
    }
  }
}