MVVM UserControl 绑定未推回到父控件
我正在制作一个 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 中,它有一个名为的子 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 得到更新时,绑定到父级的值view 不会在父视图模型中设置(即set 方法永远不会运行)。
显然,我缺少某种数据绑定连接,但我一生都无法弄清楚那是什么,我已经搜索遍了,但一无所获。
更新
最小工作示例。包括我正在使用的大部分专有日期类,以及可能一些较差的 MVVM 实现。我还是 MVVM 的新手。我删除了很多不必要的代码,因此日期选择器无法正常工作,但它完成了本问题所需的操作。
您需要获取并引用 MvvmFoundation.Wpf.dll
(位于 codeplex)。
I'm working on making a WPF app and I have a UserControl for data editing with a couple more UserControls inside it (super-simplified version):
<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>
In the parent control's ViewModel, it has a child DatePickerViewModel
called EndDate
which is bound to the DatePickerView
control:
public class ParentControlViewModel : ViewModelBase
{
private DatePickerViewModel _endDate;
public DatePickerViewModel EndDate
{
get { return _endDate; }
set
{
_endDate = value;
RaisePropertyChanged(() => EndDate);
RaisePropertyChanged(() => SomeProperty);
}
}
}
The DatePickerView
control is a few comboboxes that are bound to properties in a DatePickerViewModel
, nothing special.
When I run my app, the DatePickerView
is initialized properly and is set to the current value, like it should be. So the get
method is working fine. But when I change the controls on the DatePickerView
and its ViewModel gets updated, the value bound to the parent view doesn't get set in the parent view model (i.e. the set
method never runs).
Obviously I am missing some sort of databinding hookups but for the life of me I cannot figure out what that is and I have searched all over and found nothing.
Update
Minimal working sample. Includes most of the proprietary date class I'm using, and probably some poor MVVM implementations. I'm still new at MVVM. I ripped a lot of the unnecessary code out so the date picker doesn't work quite right, but it does what it needs to do for the purposes of this question.
You will need to get and reference MvvmFoundation.Wpf.dll
(at codeplex).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
唯一有意义的事情(仅基于显示的代码)是(1)ViewModelBase 没有实现 INotifyPropertyChanged 或(2)您的 DatePickerView 控件在依赖属性方面做了错误的事情。
我建议发布完整的重现,包括 DataPickerView 和 ViewModelBase。
编辑
好的,看了一下,发现问题了。你的 setter 永远不会被调用的原因是你的 EndDate (DatePickerViewModel) 永远不会改变。这听起来有点不言而喻,但这就是底线——没有代码可以完全替换 EndDate 属性,这将导致 setter 代码运行。
您的下拉列表会更改 EndDate/DatePickerViewModel 的属性,但请记住,更改其属性(Date、SelectedYear 等)不会设置 DatePickerViewModel 的实例,这意味着设置器代码将不会运行。
由于这是一个精简版本,我有点猜测您最终想要实现的目标,但我认为您想要的是在 DatePickerViewModel (可能是 DateTime 类型)上创建一个可以绑定并可以通知的 DependencyProperty当控件内的日期更改时。
作为快速解决方法,请添加以下代码以使 setter 代码触发。请注意,这不是推荐的解决方案 - 它会导致您的父母和孩子互相引用,这(至少)很奇怪:
The only things that would make sense (based on just the code shown) is (1) the ViewModelBase doesn't implement INotifyPropertyChanged or (2) your DatePickerView control is doing something wrong with Dependency Properies.
I would suggest posting a full repro, including DataPickerView and ViewModelBase.
Edit
Ok, took a look, and see the problem. The reason why your setter never gets called is that your EndDate (DatePickerViewModel) never changes. That sounds somewhat self-evident, but that's the bottom line--there is no code that replaces the EndDate property completely, which is what would cause the setter code to run.
Your drop down lists change the properties of EndDate/DatePickerViewModel, but keep in mind that changing its properties (Date, SelectedYear, etc.) does not set the instance of DatePickerViewModel, which means the setter code will not run.
Since this is a stripped-down version, I am kind of guessing at what you ultimately want to achieve, but I think what you want is to create a DependencyProperty on the DatePickerViewModel (probably of type DateTime) that can be bound to and can notifies when the date inside the control changes.
As a fast workaround, add the code below to make the the setter code fire. Note this is not a recommended solution--it will cause your parent and child to have references to each other, which is (at least) odd: