Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过我自己的代码检测对DependencyProperty的更改_C#_.net_Wpf_Dependency Properties - Fatal编程技术网

C# 通过我自己的代码检测对DependencyProperty的更改

C# 通过我自己的代码检测对DependencyProperty的更改,c#,.net,wpf,dependency-properties,C#,.net,Wpf,Dependency Properties,我的控件有一个映射到私有变量的属性。设置属性时,我还需要存储某个其他变量。当属性的私有变量由我自己的控制代码设置时,不能进行这种特殊处理。一切都好 我现在需要将其重构为DependencyProperty。我这里只有一个更改处理程序,对该属性的所有(也是内部)访问都必须通过DependencyProperty框架。没有更多的私有变量可以直接设置。现在,我自己的代码所做的每一项更改看起来都与来自外部源(如控件或数据绑定的用户)的更改完全相同 在我的属性更改处理程序中,如何确定值更改是来自我的代码还

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

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

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

这是旧代码:

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;

因此,当我以前分配私有变量时,我现在只能设置dependency属性,它也将更改
intendedDay

为什么不将dependency属性包装为普通属性?设置属性仍然会设置dependency属性,而设置private属性不会设置intendedDay值

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

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

正如克莱门斯在评论中解释的那样,我添加了一个私有变量,用于指示我当前是否正在从自己的代码更新该属性。每当我想要抑制外部值更改处理时,我都将其设置为true,然后设置为false。因此,我可以区分是内部值更改还是外部值更改。

问题在于,使用依赖项属性时,您无法访问实际的数据存储。(CLR属性只是代码的快捷方式。其他方法不需要使用它。)并且可以通过绑定直接更改实际的数据存储,中间没有层。这也必须始终设置
intendedDay
。现在,我自己的控制代码如何才能在不更改预定日期的情况下更改属性值?啊,我明白了。因此,如果SetValue必须始终设置intendedDay(如果被除此之外的任何调用),那么我们有一个有趣的问题。让我仔细考虑一下你的评论,看起来你已经想出了一个有效的解决方案。我不知道有任何CLR magig允许您在不使用反射和stackframe=slow and ught的情况下确定SetValue方法的调用方。我记得当Windows关闭或应用程序退出时,会出现类似关闭原因的情况。依赖项属性可能也有类似的“更新原因”。StackFrame没有选择,它太容易失败,而且成本太高。当需要时,我可以在控件中设置这两个变量。问题是我只需要改变一个。但是当另一个也被自动更新时,它们都粘在一起了。我可以建议使用一个丑陋的解决方案,带有私有标志和特殊的SetSelectedTime方法,它使用此标志来控制
SelectedTimeChanged
。但这是一个棘手的问题,可能会导致一些并发问题。我提出了一个InternalSetValue方法,该方法设置标志,然后调用SetValue,然后清除标志。啊,你是说
私有bool正在更新
,它是围绕设置依赖项属性设置的
true
,并在更改处理程序中进行计算的?