2017-10-05 37 views
0

我有一个带有PropertyChangedCallback的依赖属性的自定义控件。该属性的值可能会从自定义控件的逻辑中或从无(通过用户交互或通过从客户端应用程序设置的值)更改。PropertyChangeCallback - 是否在控制范围内进行更改

有没有一种方法可以告诉哪些导致财产改变?

我试着看着“发件人”,但在每种情况下,发件人都是自定义控件本身。

举例说明:

public static readonly DependencyProperty SelectedTimeProperty = 
     DependencyProperty.Register("SelectedTime", typeof(DateTime?), typeof(TimePickerControl), new PropertyMetadata(null, new PropertyChangedCallback(HandleSelectedTimeChanged))); 

    public static readonly DependencyProperty HoursProperty = 
     DependencyProperty.Register("Hours", typeof(object), typeof(TimePickerControl), new PropertyMetadata(@"", (o, e) => ((TimePickerControl)o).OnHoursChanged(o, e.OldValue))); 

    public static readonly DependencyProperty MinutesProperty = 
     DependencyProperty.Register("Minutes", typeof(object), typeof(TimePickerControl), new PropertyMetadata(@"", (o, e) => ((TimePickerControl)o).OnMinutesChanged(o, e.OldValue))); 

    public static readonly DependencyProperty SecondsProperty = 
     DependencyProperty.Register("Seconds", typeof(object), typeof(TimePickerControl), new PropertyMetadata(@"", (o, e) => ((TimePickerControl)o).OnSecondsChanged(o, e.OldValue))); 

所以客户端应用程序既可以更新SelectedTime,在这种情况下HoursMinutesSeconds将由控制进行更新。该逻辑在HandleSelectedTimeChanged中处理。

然而,用户还可以修改Hours之一,MinutesSeconds其中SelectedTime就必须进行相应的更新。

正如您大概猜测的那样,这会创建一个循环,因为例如Hours的更改会导致SelectedTime回调被触发,这当然会更改调用其回调的小时/分钟/秒再次触发。

我想要么只调用回调,如果改变来自控制之外,或者在回调中检测到这一点,所以直接退出。

我到目前为止唯一的想法是在更改其中一个属性之前设置一个私有变量,并在其回调出口内设置,然后在更改后立即清理它,但这看起来很杂乱对我来说。有没有更好的方法来做到这一点?

+0

依赖项属性在控件中。如果你也在控制中改变它们的值,那么只需使用一些标志:在改变之前设置它,在回调中检查它。另一件事是[强制](https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-property-callbacks-and-validation#coerce-value-callbacks-and-property-changed -events)。 – Sinatr

+1

_“你可能会猜到,这会产生一点循环”_这不应该发生。只有在属性值_actually changes_时,才会调用属性更改回调。因此,如果您更改'Hours'属性,则其回调大概会设置SelectedTime属性,该属性将再次设置“Hours”属性值。但是,'Hours'属性值没有改变,所以它的属性改变了回调函数将不会被调用。我怀疑你的问题更多地与你的'Hours','Minutes'和'Seconds'依赖属性声明为类型**对象**有关。他们应该是** int **吗? –

+0

@StevenRands - 这不是一个无限循环,我意识到你在说什么,但它创造了一个复杂的意大利面条流,这使得读取/调试/维护变得困难,并且可能导致控制中的其他问题。 – colmde

回答

0

至于只从外面发射变化事件,恐怕是不可能的。 这是一种非常常见的情况,您正面临着一些解决方案。

  1. 第一个也是最好的解决方案是完全避免这种情况。

在您的情况下,它是指取代具有的时间每个组件多重依赖性性质只写为每个自定义值转换器,然后将值绑定到所述单个SelectedTime属性与所需的转换器。我个人高度推荐这种方法。

  1. 第二种方法是根据需要进行更改。

在你的情况下,这意味着在触发之前UpdateHour检查是否应该更新小时。如果不是不触发它。这是一个干净的方法,将会削减更新的循环,但是会有性能开销。

  1. 第三种方法是有脏标志。

这有点像你说的。对于SelectedDate,您保留一个布尔标志,其值为false。当它发生变化时,将其设置为true,并在下一个循环中如果它为true,则退出并将其设置为false。

正如你所说,它是凌乱和不洁。但完成工作。

+0

为什么downvote?谨慎发表评论? – Emad

+1

我用“肮脏的旗帜”的方法... – colmde