【问题标题】:PropertyChangeCallBack not firing on DependencyProperty in a UserControlPropertyChangeCallBack 未在 UserControl 中的 DependencyProperty 上触发
【发布时间】:2011-05-21 07:48:24
【问题描述】:

难过:我正处于创建需要执行一些 UI 操作的月份计划器控件的初始阶段 I 当提供来自 XAML 中绑定的 ViewModel 的日期时的控件。当我运行代码时,ViewModel 确实返回了值,但 PropertyChangeCallBack 没有触发。我在public class ExtendedDataGrid : DataGrid 控件中做了完全相同的事情,并且工作正常,但几乎就像您必须对 UserControls 做一些不同的事情。这是我的代码的基础:

public partial class DiaryMonthViewUserControl : UserControl
{
    private DateTime _topDate;


    public DiaryMonthViewUserControl()
    {
        InitializeComponent();
    }

    // Property to get the date from the ViewModel for processing. This will fire and event to set the month we want to display
    public static readonly DependencyProperty TheDateProperty = DependencyProperty.Register("TheDate", typeof(DateTime),
                      typeof(DiaryMonthViewUserControl),
                      new FrameworkPropertyMetadata(DateTime.Today, OnDatePropertyChanged, null));

    public void SetTheCurrentDate(DateTime CurrentDate)
    {
        _topDate = CurrentDate;

        // Like Outlook, whatever date we supply, I want the first top level displayed date for the month
        if (_topDate.Day > 1)
            _topDate = _topDate.AddDays(-(_topDate.Day-1)); // First day of the month

        // Get to the first Monday before the 1st of the month if not on a Monday
        while (_topDate.DayOfWeek != DayOfWeek.Monday)
            _topDate = _topDate.AddDays(-1);

        // I will set the UI here once I have solved this problem.
        MakeChangesToTheUIPlease();
    }

    private static void OnDatePropertyChanged(DependencyObject Source, DependencyPropertyChangedEventArgs e)
    {
        var control = Source as DiaryMonthViewUserControl;

        if (control != null)
            control.SetTheCurrentDate((DateTime)e.NewValue);
    }

    [Bindable(true)]
    public DateTime TheDate
    {
        get { return (DateTime)GetValue(TheDateProperty); }
        set { SetValue(TheDateProperty, value); }
    }
}

我也尝试使用new PropertyChangedCallback(OnDatePropertyChanged) 作为参数,但仍然不起作用。

我的绑定如下:

<my:DiaryMonthViewUserControl HorizontalAlignment="Left" Margin="12,12,0,0" x:Name="diaryMonthViewUserControl1" 
                              VerticalAlignment="Top" Height="325" Width="476" TheDate="{Binding Path=CurrentDate}" />

当我运行代码时,我的 ViewModel 会在 CurrentDate 的 getter 上中断,如果我删除 CurrentDate 绑定,那么它不会。问题是回调没有触发,而且我这辈子都无法理解为什么。

任何帮助都将不胜感激,特别是可能涵盖此问题的文章的链接。

【问题讨论】:

  • 你提到你可以在 getter 上中断,但回调不是会被触发 setter 的代码触发吗?
  • 好的,我刚刚发现了一些不是答案但更接近的东西。如果我使用完全相同的代码,但将类型更改为 int,那么它是有效的,但 DateTime 类型不是。将 DateTime 类型作为依赖属性是否存在已知问题?
  • Wpf 新手,但 WiForms 编程的老手,我觉得我可以猜到它是如何工作的。我的 XAML 中的绑定到依赖属性调用视图模型上绑定属性的 getter,然后为依赖属性设置 GetValue() 和 SetValue() 中的值,然后它将触发更改的回调事件。 Binding 确实从视图模型中提取值,但根本不做任何其他事情。我想我一定是遗漏了一些本应公开的东西或将某些东西设为私有,因为我之前已经创建了几个依赖属性
  • 然而,真正奇怪的是,当我将属性类型从 DateTime 更改为 string 或 int 然后更改所有其他相应的属性并调用以匹配该类型时,它可以工作。就像 DateTime 不适用于依赖属性,但我知道它们可以。在用户控件上创建依赖属性时我需要考虑什么?

标签: wpf xaml dependency-properties


【解决方案1】:

PropertyChanged 回调仅在 立即属性 更改时触发,这意味着需要替换整个 DateTime 对象,如果更改 DateTime 对象的属性,则不会引发事件。这就是它适用于 int 等原始类型的原因。

如果您想在 DateTime 的任何属性更改时执行某些方法,您可以实现一个提供通知的 DateTime 类。然后,您可以在任何属性更改时执行该方法。

【讨论】:

  • 太棒了 - 非常感谢,大约 2 分钟后我意识到我需要返回 new DateTime(dateObj.Year, dateObj.Month, dateObj. Day) 从我的视图模型中,而不是简单地返回 dateObj;正如你所说,这会为 dateTime 创建一个全新的对象,因为它不是一个原始类型,它会强制触发 on change 回调事件。
  • 啊 - 现在我尝试返回 new DateTime 并认为它有效,但随后意识到我已将值类型转换为原始类型 int,但无论如何它仍然有效。将其转换回 dateTime 然后用 new 尝试仍然不起作用。寻找更多想法或更清楚您的建议。
  • 我建议您创建一个基本上是可绑定 DateTime 的类,当其中一个属性发生更改时,它会为您提供更改通知,然后您可以订阅所有这些并调用您的更新方法。我不知道你所有的类是什么样的,可能有更简单的方法来做到这一点。
  • 好的,我会试试这个,但对 Wpf 来说还很新,我将不得不解决这个问题。我很惊讶这不是很直接,因为我可以看到这应该经常需要。
  • 好的,我有一个解决方案,但我会感谢最后一个答案,因为它让我思考并且有一个适用于现在的解决方案。 class DateTimeObject { public DateTime TheDateTime { get; set; } } 然后只需创建一个实例并使用 DateTimeObject 类型的 DependencyProperty 将其绑定到 XAML。在我的 UserControl 中,我只需提取 DateTime 属性。不好,但在我找到更好的解决方案之前它会起作用。
猜你喜欢
  • 1970-01-01
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 1970-01-01
  • 2015-03-26
  • 1970-01-01
相关资源
最近更新 更多