使用DateTime DependencyProperty在WPF中实现双向绑定

时间:2014-10-02 13:44:10

标签: c# wpf datepicker dependency-properties

我已经构建了一个WPF用户控件,其中包含一个DatePicker以及其他控件。我的应用程序是用MVVM设计模式编写的。我希望能够将我的用户控件插入到视图中,并将用户控件的DatePicker的SelectedDate属性绑定到我视图的ViewModel上的DateTime属性。我希望显示的默认值是我视图的viewmodel中存储的值,我希望通过与DatePicker的交互来更改日期,以更新我的view的viewmodel DateTime属性。

我已成功查看DatePicker控件中显示的正确绑定值,但是当我更改日期时,我的视图的viewmodel的DateTime属性设置器未触发。

这就是我的用户控件的代码隐藏:

public partial class AgeDiscountUserControl : UserControl
{
    public AgeDiscountUserControl()
    {
        InitializeComponent();
    }

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

    public static readonly DependencyProperty DateTimeProperty =
        DependencyProperty.Register("DateTime", typeof(DateTime), typeof(AgeDiscountUserControl));
}

在我的用户控件的XAML中,我有:

...
xmlns:my="clr-namespace:jkshay.UserControls"
...
<DatePicker Grid.Row="0" SelectedDate="{Binding DateTime, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType=my:AgeDiscountUserControl}}" DockPanel.Dock="Right"/>
...

在我视图的viewmodel(实现INotifyPropertyChanged)中,我有一个DateTime属性,我想绑定我的用户控件的DatePicker的SelectedDate属性。

...
private DateTime birthdate;
public DateTime Birthdate
{
    get { return birthdate; }    
    set
    {
        if(birthdate != value)
        {  
            birthdate = value;
            NotifyPropertyChanged(() => Birthdate);
        }
    }
}
...

最后,在我看来的XAML中,我的AgeDiscountUserControl的绑定是:

...
<uc:AgeDiscountUserControl DateTime="{Binding Birthdate}"/>
...

如前所述,正确的值最初显示在用户控件的DatePicker中,但DatePicker所做的更改不会影响绑定属性。

我在这里遗漏了什么,或者我只是完全误解了DependencyProperties?

我应该提一下,如果我在视图中插入一个DatePicker并将其绑定到我的viewmodel的Birthdate属性,它会按预期工作。

2 个答案:

答案 0 :(得分:1)

正如您已经想到的那样,Binding必须是双向的,以确保在目标控件的值更改时更新源。但是您无需明确地执行此操作:您可能希望将双向绑定设置为DateTime属性的默认值。您可以通过在注册依赖项属性时指定标志来执行此操作:

public static readonly DependencyProperty DateTimeProperty =
    DependencyProperty.Register(
        "DateTime",
        typeof(DateTime),
        typeof(AgeDiscountUserControl),
        new FrameworkPropertyMetadata(
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault // <--
        )
    );

答案 1 :(得分:0)

根据Sinatr的建议,我在我的视图的XAML中添加了Mode = TwoWay设置,现在一切都按预期工作。

更新的相关XAML是:

<uc:AgeDiscountUserControl DateTime="{Binding Birthdate, Mode=TwoWay}"/>

我现在看到我的Birthdate setter在与用户控件交互时触发。感谢您的建议,Sinatr。