简体   繁体   English

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

[英]Implementing two-way binding in WPF with a DateTime DependencyProperty

I've built a WPF user control that contains, among other controls, a DatePicker. 我建立了一个WPF用户控件,其中包含一个DatePicker。 My application is written with the MVVM design pattern. 我的应用程序是使用MVVM设计模式编写的。 I want to be able to insert my user control into a view and bind the user control's DatePicker's SelectedDate property to a property of DateTime on my view's ViewModel. 我希望能够将用户控件插入视图中,并将用户控件的DatePicker的SelectedDate属性绑定到视图的ViewModel上的DateTime属性。 I want the default value shown to be the value stored on my view's viewmodel, and I want changes to the date through interaction with the DatePicker to update my view's viewmodel DateTime property. 我希望显示的默认值是存储在视图的ViewModel中的值,并且希望通过与DatePicker交互来更改日期以更新视图的ViewModel DateTime属性。

I'm successfully seeing the proper bound value displayed in the DatePicker control, but when I change the date my view's viewmodel's DateTime property setter is not firing. 我成功地看到在DatePicker控件中显示了正确的绑定值,但是当我更改日期时,视图的viewmodel的DateTime属性设置器未触发。

This is what I have for my user control's code-behind: 这是我的用户控件背后的代码:

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));
}

And in my user control's XAML, I have: 在用户控件的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"/>
...

In my view's viewmodel (which implements INotifyPropertyChanged), I've a DateTime property to which I'd like to bind my user control's DatePicker's SelectedDate property. 在我视图的viewmodel(实现INotifyPropertyChanged)中,我有一个DateTime属性,我想将用户控件的DatePicker的SelectedDate属性绑定到该属性。

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

Finally, in my view's XAML, my AgeDiscountUserControl's binding is: 最后,在我的视图的XAML中,我的AgeDiscountUserControl的绑定是:

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

As stated previously, the proper value is initially displayed in the user control's DatePicker, but changes made by the DatePicker don't affect the bound property. 如前所述,正确的值最初显示在用户控件的DatePicker中,但是DatePicker所做的更改不会影响bound属性。

Am I missing something here, or do I simply have a complete misunderstanding of DependencyProperties? 我是否在这里遗漏了一些东西,还是对DependencyProperties完全误解了?

I should mention that if I insert a DatePicker in my view and bind it to my viewmodel's Birthdate property, it works as expected. 我应该提到,如果我在视图中插入DatePicker并将其绑定到我的视图模型的Birthdate属性,它将按预期工作。

As you have already figured out, the Binding must be two-way to ensure the source is updated when the target control's value changes. 如您所知, Binding必须是双向的,以确保在目标控件的值更改时更新源。 But you need not do that explicitly: you may want to make two-way binding the default for your DateTime property. 但是您不必显式地执行此操作:您可能希望将双向绑定设置为DateTime属性的默认值。 You can do this by specifying a flag when you register your dependency property: 您可以通过在注册依赖项属性时指定一个标志来做到这一点:

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

On Sinatr's suggestion, I added a Mode=TwoWay setting to my view's XAML, and everything now works as expected. 根据Sinatr的建议,我在视图的XAML中添加了Mode = TwoWay设置,现在一切正常。

Updated pertinent XAML is: 更新的相关XAML是:

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

I now see my Birthdate setter firing upon interaction with the user control. 现在,我看到与用户控件进行交互时会触发我的Birthdate setter。 Thanks for the suggestion, Sinatr. 谢谢你的建议,辛纳特尔。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM