Reputation: 145
i have a user control. I want to create a bindable property in my user control. I create a DependencyProperty as follows:
public static readonly DependencyProperty DateProperty =
DependencyProperty.Register("Date", typeof(DateTime), typeof(DaiesContainer),
new UIPropertyMetadata(DateTime.Now));
public DateTime Date
{
get { return (DateTime)GetValue(DateProperty); }
set
{
SetValue(DateProperty, value);
}
}
I then use it in my XAML:
<ctrls:DaiesContainer Date="{Binding Date, Mode=OneWay}"/>
In my ViewModel, the get method of the Date property is called. But in my user control, Date property is not set to a value.
Upvotes: 7
Views: 17625
Reputation: 128136
Your dependency property implementation is missing a PropertyChangedCallback
that gets called when the value of the property has changed. The callback is registered as a static method, which gets the current instance (on which the property has been changed) passed as its first parameter (of type DependencyObject
). You have to cast that to your class type in order to access instance fields or methods, like show below.
public static readonly DependencyProperty DateProperty =
DependencyProperty.Register("Date", typeof(DateTime), typeof(DaiesContainer),
new PropertyMetadata(DateTime.Now, DatePropertyChanged));
public DateTime Date
{
get { return (DateTime)GetValue(DateProperty); }
set { SetValue(DateProperty, value); }
}
private void DatePropertyChanged(DateTime date)
{
//...
}
private static void DatePropertyChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DaiesContainer)d).DatePropertyChanged((DateTime)e.NewValue);
}
Please note also that setting a default value of the dependency property is only done once for all instances of your class. Setting a value of DateTime.Now
will hence produce the same default value for all of them, namely the time at which the static DependencyProperty
is registered. I guess using something more meaningful, perhaps DateTime.MinValue
, would be a better choice. As MinValue
is already the default value of a newly created DateTime
instance, you may even omit the default value from your property metadata:
public static readonly DependencyProperty DateProperty =
DependencyProperty.Register("Date", typeof(DateTime), typeof(DaiesContainer),
new PropertyMetadata(DatePropertyChanged));
Upvotes: 12
Reputation: 19296
I think that you have error in XAML UserControl.
You should binding by ElementName
, e.g.:
<UserControl x:Class="WPFProject.DaiesContainer"
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="300" d:DesignWidth="300"
x:Name="daiesContainer">
<Grid>
<DatePicker SelectedDate="{Binding Date, ElementName=daiesContainer}" />
</Grid>
</UserControl>
In this case you binding to Date
property of DaiesContainer
class.
If you use binding without ElementName
:
<DatePicker SelectedDate="{Binding Date}" />
UserControl DaiesContainer
will trying find property Date
in DataContext
of container this user control, and if it will not find this property, you will see DatePicker
with empty selected value.
Upvotes: 0
Reputation: 8902
Make your binding Mode TwoWay
<ctrls:DaiesContainer Date="{Binding Date, Mode=TwoWay}"/>
Upvotes: 0