I need to create a control with few inputs / output with lots of internal functionality. I think the best approach is to create Dependency Properties
for interaction with other application parts and have a private
view model
with hidden functions.
Here is my sample:
Window
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfApplication1">
<StackPanel>
<DatePicker x:Name="DatePicker" />
<app:MyControl DateCtrl="{Binding ElementName=DatePicker, Path=SelectedDate}" />
</StackPanel>
</Window>
MyControl
<UserControl x:Class="WpfApplication1.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfApplication1">
<UserControl.DataContext>
<app:ViewModel />
</UserControl.DataContext>
<Grid>
<TextBlock Text="{Binding DateVM}" />
</Grid>
</UserControl>
Control code-behind
using System;
using System.Windows;
namespace WpfApplication1
{
public partial class MyControl
{
public MyControl()
{
InitializeComponent();
}
public static DependencyProperty DateCtrlProperty = DependencyProperty.Register("DateCtrl", typeof(DateTime), typeof(MyControl));
public DateTime DateCtrl
{
get { return (DateTime) GetValue(DateCtrlProperty); }
set { SetValue(DateCtrlProperty, value); }
}
}
}
ViewModel
using System;
using System.ComponentModel;
namespace WpfApplication1
{
public class ViewModel : INotifyPropertyChanged
{
private DateTime _dateVM;
public DateTime DateVM
{
get { return _dateVM; }
set
{
_dateVM = value;
OnPropertyChanged("DateVM");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I need to achieve is to propagate date
chosen in DatePicker
down to MyControl's
view model
. Alternatively, is there any better pattern to use?
What you describe is a common misconception that all views should have a view model. However, it is usually far simpler (and more appropriate) for
UserControl
s that are used as controls to simply use their ownDependencyProperty
s.The problem with your method is that you have assigned the
UserControl DataContext
internally, so it cannot be set from outside the control. The solution is to not set theDataContext
internally, but instead to use aRelativeSource Binding
to access theUserControl DependencyProperty
s like this:If you really have to use an internal view model, then declare a
DependencyProperty
of that type and data bind to it in the same way that I showed above: