我學(xué)習(xí)WPF使用的是《WPF編程寶典》(第四版)肋拔。之前讀到自定義控件,也就是18.2顏色拾取器的時(shí)候,有一句話我深深的記在腦海里胎署。
因?yàn)閃PF不允許重新進(jìn)行屬性變化回調(diào)函數(shù)琳骡。
多么智能东揣,多么貼心循衰。為了避免有的人沒(méi)有看過(guò)這本書继低,我把書里的例子貼在這里。
public class ColorPicker:System.Windows.Controls.UserControl
{
public static DependencyProperty RedProperty;
public static DependencyProperty GreenProperty;
public static DependencyProperty BlueProperty;
public static DependencyProperty ColorProperty;
static ColorPicker()
{
ColorProperty = DependencyProperty.Register("Color", typeof(Color),
typeof(ColorPicker), new FramewrokPropertyMetadata(Colors.Black, new PropertyChangedCallback(OnColorChanged));
RedProperty = DependencyProperty.Register("Red", typeof(byte),
typeof(ColorPicker), new FramewrokPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged));
GreenProperty = DependencyProperty.Register("Green", typeof(byte),
typeof(ColorPicker), new FramewrokPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged));
BlueProperty = DependencyProperty.Register("Blue", typeof(byte),
typeof(ColorPicker), new FramewrokPropertyMetadata(new PropertyChangedCallback(OnColorRGBChanged));
}
public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
public byte Red
{
get { return (byte)GetValue(RedProperty); }
set { SetValue(RedProperty, value); }
}
public byte Green
{
get { return (byte)GetValue(GreenProperty); }
set { SetValue(GreebProperty, value); }
}
public byte Blue
{
get { return (byte)GetValue(BlueProperty); }
set { SetValue(BlueProperty, value); }
}
private static void OnColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Color newColor = (Color)e.NewValue;
Color oldColor = (Color)e.OldValue;
ColorPicker colorPicker = (ColorPicker)sender;
colorPicker.Red = newColor.R;
colorPicker.Green = newColor.G;
colorPikcer.Blue = newColor.B;
}
private static void OnColorRGBChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ColorPicker colorPicker = (ColorPicker)sender;
Color color = colorPicker.Color;
if (e.Property == RedProperty)
color.R = (byte)e.NewValue;
else if (e.Property == GreenProperty)
color.G = (byte)e.NewValue;
else if (e.Property == BlueProperty)
color.B = (byte)e.NewValue;
colorPicker.Color = color;
}
}
很明顯劳澄,這段代碼是希望在改變RGB的值時(shí),能夠更新Color蜈七。同時(shí)在更新Color時(shí)秒拔,能夠更新RGB。并且飒硅,這樣寫并不會(huì)造成循環(huán)調(diào)用砂缩。
我一直堅(jiān)信這是WPF內(nèi)部進(jìn)行優(yōu)化,能夠保證在任何情況下三娩,callback中對(duì)依賴屬性進(jìn)行設(shè)置庵芭,不會(huì)發(fā)生循環(huán)調(diào)用的情況。
知道今天雀监,我把對(duì)應(yīng)的Color改成了TimeSpan双吆,循環(huán)調(diào)用發(fā)生了。那一刻会前,我是懷疑人生的好乐。
先給出結(jié)論:DependencyPropertyChangedCallback中并不會(huì)進(jìn)行什么神奇的操作來(lái)規(guī)避循環(huán)調(diào)用。能夠規(guī)避部分循環(huán)調(diào)用的原因時(shí)瓦宜,SetValue會(huì)對(duì)值進(jìn)行判定蔚万,如果值沒(méi)有發(fā)生改變,則不會(huì)調(diào)用DependencyPropertyChangedCallback临庇。
為什么改成TimeSpan類型會(huì)發(fā)生循環(huán)調(diào)用呢反璃?因?yàn)槿绻裇econd賦值一個(gè)超過(guò)60的數(shù)昵慌,會(huì)進(jìn)位。感興趣的朋友可以想想為什么淮蜈。歡迎留言討論斋攀。