Reputation: 5083
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.
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).
Upvotes: 2
Views: 815
Reputation: 28016
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:
//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;
}
}
}
Upvotes: 1