datagrid自定义列上的依赖项属性回调未触发

时间:2013-06-06 12:43:17

标签: wpf data-binding dependency-properties datagridcolumn

我有以下自定义datagrid列,用于将DatePart依赖项属性的值作为ConverterParameter传递给编辑元素的转换器:

Public Class DataGridTimeColumn
    Inherits DataGridTextColumn

    Shared ReadOnly DatePartProperty = DependencyProperty.Register("DatePart", GetType(DateTime?), GetType(DataGridTimeColumn), New FrameworkPropertyMetadata(Nothing, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, AddressOf RefreshBinding))
    Property DatePart As DateTime?
        Get
            Return GetValue(DatePartProperty)
        End Get
        Set(value As DateTime?)
            SetValue(DatePartProperty, value)
        End Set
    End Property

    Private Shared Sub RefreshBinding(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
        Dim tc As DataGridTimeColumn = d
        tc.Binding = tc.Binding
    End Sub

    Public Overrides Property Binding As BindingBase
        Get
            Return MyBase.Binding
        End Get
        Set(value As BindingBase)
            Dim b As Data.Binding = value
            With b
                .Converter = New TimeConverter
                .ConverterParameter = DatePart
            End With
            MyBase.Binding = b
        End Set
    End Property
End Class

使用以下XAML:

<my:DataGridTimeColumn Header="From" Binding="{Binding FromDate}" DatePart="{Binding FromDate}" />
<my:DataGridTimeColumn Header="Until" Binding="{Binding TillDate}" DatePart="{Binding TillDate}" />

RefreshBinding永远不会被调用(我设置了一个断点并且它永远不会被触发),因此DatePart总是NothingnullConverterParameter 1}}已设置。我该如何解决这个问题?

修改

在C#中:

public class DataGridTimeColumn : DataGridTextColumn
{
    static readonly DependencyProperty DatePartProperty = DependencyProperty.Register(
        "DatePart", typeof(DateTime?), typeof(DataGridTimeColumn),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, RefreshBinding)
    );

    public DateTime? DatePart
    {
        get { return (DateTime?)GetValue(DatePartProperty); }
        set { SetValue(DatePartProperty, value); }
    }

    private static void RefreshBinding(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    {
        var tc = (DataGridTimeColumn)d;
        tc.Binding = tc.Binding;
    }

    public override System.Windows.Data.BindingBase Binding
    {
        get { return base.Binding; }
        set
        { 
            var b = (Binding)value;
            b.Converter = new TimeConverter();
            b.ConverterParameter = DatePart;
            base.Binding = b;
        }
    }
}

4 个答案:

答案 0 :(得分:0)

我可能不明白你正在尝试做什么,但这看起来像查看/编辑DatePart需要做很多工作。使用格式化程序和DataGridTextColumn会更容易吗? WPF Binding StringFormat Short Date String

答案 1 :(得分:0)

首先,请使用debug检查绑定路径是否正常。 其次,检查FromDate属性是否被触发。 第三,请使用Snoop监控此DP是否更新。

最后,我记得DataGrid有动态绑定错误,所以我不确定上面的步骤可以解决你的问题。如果不行,请告诉我。

答案 2 :(得分:0)

如果您只需要格式化值,我会推荐Darlene方法。如果你真的需要一个魔法转换器,我会建议你通过XAML中的绑定设置它(我真的不知道你为什么要在属性定义中设置它)。

您的XAML将是这样的:

 <my:DataGridTimeColumn Header="From" Binding="{Binding FromDate, Converter={StaticResource myTimeConverter}} />

TimeConverter必须实现IValueConverter,并且必须在window / datagrid资源中定义实例。您还可以在该绑定中定义TwoWay。

您可以找到完整的示例here

如果您想要合并两个或多个数据,可以使用MultiBinding

答案 3 :(得分:0)

试图从评论中了解您想要实现的目标,如果我做得对,您只能使用视图模型和具有小解决方案的转换器来实现:

在转换器ConvertBack方法中,您可以尝试确定用户输入的值是否只包含时间部分,如果是,则将日期设置为不使用的值(例如DateTime.MinValue):

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    var convertedDateTime = DateTime.Parse(value.ToString());
    var hasOnlyTime = value.ToString().Trim().Length <= 5; // This should be replaced with something more consistent

    if (hasOnlyTime)
        return new DateTime(DateTime.MinValue.Year, DateTime.MinValue.Month, DateTime.MinValue.Day, convertedDateTime.Hour, convertedDateTime.Minute, convertedDateTime.Second);

    return convertedDateTime;
}

然后在日期的对象设置器中,您可以检查并使用所需的值,如果日期部分是DateTime.MinValue,则将其更改回上一个,如果没有保持原样:

 private DateTime _fromDate;
 public DateTime FromDate
 {
    get { return _fromDate; }
    set 
    {
        if (value.Date != DateTime.MinValue)
            _fromDate = value;
        else
            _fromDate = new DateTime(_fromDate.Year, _fromDate.Month, _fromDate.Day, value.Hour, value.Minute, value.Second);

        OnPropertyChanged("FromDate");
    }
 }

在.NET 4.5上测试并按预期工作。