我正在制作一个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.dll
(at codeplex)。
答案 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;
}
}
}