3
votes

As the title says, I want to bind a property from my ViewModel to a nested UserControl in the corresponding view. I cant get it work the way I need.

The nested UserControl is nothing more than a DatePicker and a DropDown for the hours. How can I tell the DatePicker to choose the date propagated by the ViewModel as its selected date?

I tried nearly everything and now I'm not far away from jumping outside the window. As you can see any help is appreciated ;)

Now to the code so far: DateTimePicker.xaml.cs (CodeBehind)

public partial class DateTimePicker
{
    public static DependencyProperty SelectedDateValueProperty = DependencyProperty.Register("SelectedDateValue", typeof (DateTime), typeof (DateTimePicker), new FrameworkPropertyMetadata(default(DateTime), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnPropertyChangedCallback));

    private static void OnPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        Debug.WriteLine("Wohoo. I'm here and still debugging...");
    }

    public DateTimePicker()
    {
        InitializeComponent();

        DataContext = this;

        var times = GetTimes();

        Times.ItemsSource = times;
        Times.SelectedItem = times.First();
    }

    public DateTime SelectedDateValue
    {
        get { return (DateTime) GetValue(SelectedDateValueProperty); }
        set { SetValue(SelectedDateValueProperty, value); }
    }
}

The nested UserControl (DateTimePicker.xaml):

<UserControl x:Class="Framework.Controls.DateTimePicker"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         mc:Ignorable="d" 
         d:DesignHeight="30" d:DesignWidth="200"
         DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="3*" />
        <ColumnDefinition Width="2*" />
    </Grid.ColumnDefinitions>
    <DatePicker HorizontalAlignment="Left" Name="DatePickerCalendar" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Center" SelectedDate="{Binding SelectedDateValue}" />
    <ComboBox Grid.Column="1" VerticalAlignment="Center" Name="Times" DisplayMemberPath="Name" />
</Grid>

And, last but not least: The View which has the nested UserControl (View.xaml)

<CustomControls:DateTimePicker SelectedDateValue="{Binding LocalRegistrationStartDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

Hope the problem is clear and anybody can help me or get the point at what i am doing wrong here.

2

2 Answers

6
votes

Using:

"{Binding SelectedDateValue}"

tells WPF "Hey check my DataContext for a property called SelectedDateValue".

What you want is, to get the Property from your user control.

The easiest way is to give your user control a name like:

<UserControl x:Name="myControl"/>

and then modify your binding to :

"{Binding ElementName=myControl, Path=SelectedDateValue}"
1
votes

The usual way WPF controls are implemented is to use a template rather than defining the control as direct content, like you're doing here. By using a Template, you have access to TemplateBinding, allowing you to easily bind your control properties. See the Control Customization MSDN page.

<ControlTemplate TargetType="{x:Type local:DateTimePicker>
  ...
  <DatePicker SelectedDate="{TemplateBinding SelectedDateValue}" />
  ...
</ControlTemplate>