【问题标题】:Is it possible to override DependencyProperty to change it's type and add converter?是否可以覆盖 DependencyProperty 以更改其类型并添加转换器?
【发布时间】:2017-05-04 11:05:42
【问题描述】:

我的模型将日期存储为 DateTimeOffset。我想创建一个从 DatePicker 继承并覆盖 SelectedDate 属性的控件。我希望该属性是 DateTimeOffset 而不是 DateTime,并且我想在该自定义控件中处理从一种类型到另一种类型的转换。

我知道可以使用 DateTimeOffset 的 SelectedDate 属性创建一个 UserControl,将 DatePicker 放在该控件内并将其 SelectedDate 绑定到新的 SelectedDate 并在那里使用转换器。但我想避免这种情况,因为这需要我重新实现 DatePicker 的其他属性,我将来可能需要使用这些属性。

【问题讨论】:

  • 你有没有尝试过?您可以使用 new 关键字声明另一个 SelectedDate 属性。虽然可能是糟糕的设计......
  • 您可以为您的 DP 使用 object 类型并使用 CoerceValueCallback
  • 使用转换器绑定有什么问题?无需编写自定义用户控件即可使用绑定+转换器...
  • Clemens,你不能用 new 关键字隐藏 DP,因为绑定不是通过直接访问属性来完成的。 @AnjumSKhan,我尝试覆盖 SelectedDate 属性的元数据并处理 CoerceValueCallback,但在此之前绑定失败并且我得到的值为 null。 elgonzo,我想避免需要强制转换器的逻辑。否则每个开发人员都必须记住,您不能只将 DatePicker 绑定到模型,而必须使用转换器。
  • @NickSologoub,啊,所以你想与其他人共享控件。我假设您希望从 DatePicker 派生以保留其与 UI 相关的功能。在这种情况下,我会建议以下操作:从 DatePicker 派生控件,但保持 SelectedDate 属性不变。引入两个新属性,一个用于 DateTimeOffset,另一个用于日期偏移的原点。每当 SelectedDate 或 DateTimeOffset 发生变化时,在原点的帮助下计算另一个属性。 (1/2)

标签: c# wpf datepicker dependency-properties


【解决方案1】:

是的,可以覆盖该属性并将其转换为另一种类型,但解决方案有点棘手。问题是,如果你隐藏了原来的 SelectedDate,那么新的 SelectedDate 就不会改变,反之亦然。

这是您的控件:

using System;
using System.Windows;
using System.Windows.Controls;

public class OffsetedDatePicker : DatePicker
{
    public new DateTimeOffset? SelectedDate
    {
        get { return (DateTimeOffset)GetValue(SelectedDateOffProperty); }
        set { SetValue(SelectedDateOffProperty, value); }
    }

    public static readonly DependencyProperty SelectedDateOffProperty =
        DependencyProperty.Register(nameof(SelectedDate), typeof(DateTimeOffset?), typeof(OffsetedDatePicker), new PropertyMetadata(null, SelectedDateOffChanged));

    private static void SelectedDateOffChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var odp = d as OffsetedDatePicker;
        if (odp==null) { return; }          
        (d as DatePicker).SelectedDate = odp.SelectedDate.HasValue ? odp.SelectedDate.Value.Date : (DateTime?)null;
    }

    public OffsetedDatePicker()
    {
        SelectedDateChanged += OffsetedDatePicker_SelectedDateChanged;
    }

    private void OffsetedDatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
    {
        DateTime? newDate = null;
        if (e.AddedItems.Count > 0)
        {
            newDate = (DateTime)e.AddedItems[0];
        }
        SetValue(SelectedDateOffProperty, newDate.HasValue ? new DateTimeOffset(newDate.Value) : (DateTimeOffset?)null);
    }
}

XAML:

<local:OffsetedDatePicker SelectedDate="{Binding Path=YourVMDateTimeOffsetProp, Mode=TwoWay}" />

【讨论】:

    猜你喜欢
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    相关资源
    最近更新 更多