【问题标题】:Detecting changes to a DependencyProperty by my own code通过我自己的代码检测对 DependencyProperty 的更改
【发布时间】:2014-12-16 14:07:16
【问题描述】:

我的控件有一个映射到私有变量的属性。设置属性时,我还需要存储某个其他变量。当属性的私有变量由我自己的控制代码设置时,这种特殊处理一定不能发生。都很好。

我现在需要将其重构为 DependencyProperty。我这里只有一个更改处理程序,并且对该属性的所有(以及内部)访问都必须通过 DependencyProperty 框架。没有更多的私有变量可以直接设置。现在,我自己的代码所做的每一项更改都与来自外部源(如控件用户或 DataBinding)的更改完全相同。

在我的属性更改处理程序中,如何确定值更改是来自我的代码还是其他地方?

这是旧代码:

private DateTime selectedTime;
private int intendedDay;

public DateTime SelectedTime
{
    get { return selectedTime; }
    set
    {
        selectedTime = value;
        intendedDay = selectedTime.Day;
    }
}

在这段代码中,我可以直接设置selectedTime,而不影响intendedDay,只有在SelectedTime 被完全从外部分配一个新值时,或者当我认为适合我的控制时才能设置。

DependencyProperty 只允许我检测任何更改:

public static DependencyProperty SelectedTimeProperty = DependencyProperty.Register(
    "SelectedTime",
    typeof(DateTime),
    typeof(DateTimeTextBox),
    new PropertyMetadata(SelectedTimeChanged));

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

private static void SelectedTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
    DateTimeTextBox control = (DateTimeTextBox) obj;
    // This must not happen where I previously assigned the private variable:
    control.intendedDay = control.SelectedTime.Day;
}

private int intendedDay;

所以当我之前分配私有变量时,我现在只能设置依赖属性,这也会改变intendedDay

【问题讨论】:

  • StackFrame 是没有选择的,它太容易失败而且太贵了。我在需要时在我的控件中设置这两个变量没有问题。问题是我只需要改变一个。但是当另一个也自动更新时,它们都粘在一起了。
  • 我可以建议使用带有私有标志和特殊 SetSelectedTime 方法的丑陋解决方案,该方法使用此标志来控制SelectedTimeChanged。但它很笨拙,可能会导致一些并发问题。
  • 私有标志可能很难看,但不可避免。我想出了一个设置标志的 InternalSetValue 方法,然后调用 SetValue,然后清除标志。
  • 啊,你的意思是private bool isUpdating 围绕设置依赖属性设置true,并在更改处理程序中进行评估?

标签: c# .net wpf dependency-properties


【解决方案1】:

为什么不将您的依赖属性包装在普通属性中?设置属性仍然会设置依赖属性,设置私有属性不会设置预期日期值。

private DateTime selectedTime
{
    get { return (DateTime) GetValue(SelectedTimeProperty); }
    set { SetValue(SelectedTimeProperty, value); }
}

public DataTime SelectedTime
{
    get { return selectedTime; }
    set
    {
        selectedTime = value;
        intendedDay = selectedTime.Day;
    }
}

【讨论】:

  • 问题在于,使用依赖属性,您无法访问实际的数据存储。 (CLR 属性只是您的代码的快捷方式。其他方法不需要使用它。)而且这个实际的数据存储可以通过绑定来改变——直接没有中间层。这也必须始终设置intendedDay。现在,我自己的控制代码如何在不改变intendedDay的情况下改变属性值?
  • 啊,我明白了。因此,如果 SetValue 必须始终设置预期的日期(如果不是这个),那么我们就会遇到一个有趣的问题。让我考虑一下
  • 阅读您的 cmets,您似乎想出了一个可行的解决方案。我不知道有任何 CLR magig 允许您在不使用反射的情况下确定 SetValue 方法的调用者,并且 stackframe = 缓慢而丑陋。
  • 我记得当 Windows 关闭或应用程序退出时,会出现类似关闭的原因。依赖属性可能有类似的“更新原因”。
【解决方案2】:

就像 Clemens 在他的评论中解释的那样,我添加了一个私有变量来指示我当前是否正在从我自己的代码中更新该属性。每当我想抑制外部值更改处理时,我将其设置为 true,然后设置为 false。所以我可以区分是内部还是外部的价值变化。

【讨论】:

    猜你喜欢
    • 2011-04-28
    • 2011-05-21
    • 2011-02-20
    • 2022-01-24
    • 2020-12-22
    • 1970-01-01
    • 2019-12-06
    • 2016-02-18
    • 1970-01-01
    相关资源
    最近更新 更多