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)。
唯一有意义的事情(基于所示的代码)是(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;
}
}
}