如何修复设置属性时由于递归而导致的此问题

本文关键字:问题 递归 属性 设置 何修复 于递归 | 更新日期: 2023-09-27 18:21:17

我有一个自定义控件,如下所示:

public class UIButton : Button
{
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public new Brush Background {get; set;}
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public Color MOBG { get; set; }
    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public Color MDBG { get; set; }
    public Brush BackgroundBrush
    {
        get { return base.GetValue(BackgroundBrushProperty) as Brush; }
        set 
        {
            base.SetValue(BackgroundBrushProperty, value);
            MOBG = Functions.getLighterShade((GetValue(BackgroundBrushProperty) as SolidColorBrush).Color);
            MDBG = Functions.getDarkerShade((GetValue(BackgroundBrushProperty) as SolidColorBrush).Color);
        }
    }
    public static readonly DependencyProperty BackgroundBrushProperty =
      DependencyProperty.Register("BackgroundBrush", typeof(Brush), typeof(UIButton));
    public UIButton()
    {
        SetTemplate();
        SetEvents();
    }
    public void SetEvents()
    {
        this.PreviewMouseDown += UIButton_PreviewMouseDown;
    }
    void UIButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        Storyboard sb = new Storyboard();
        ColorAnimation c = new ColorAnimation();
        Storyboard.SetTargetProperty(c, new PropertyPath("BackgroundBrush.Color"));
        Storyboard.SetTarget(c, this);
        c.To = MDBG;
        c.Duration = new Duration(TimeSpan.FromSeconds(0.1));
        sb.Children.Add(c);
        sb.Begin();
    }
    public void SetTemplate()
    {
        ControlTemplate template = new ControlTemplate();
        FrameworkElementFactory root = new FrameworkElementFactory(typeof(Border)); root.Name = "border";
        root.SetBinding(Border.BackgroundProperty, new Binding("BackgroundBrush") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        root.SetBinding(Border.WidthProperty, new Binding("Width") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        root.SetBinding(Border.HeightProperty, new Binding("Height") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        root.SetValue(Border.CornerRadiusProperty, new CornerRadius(5));
        FrameworkElementFactory content = new FrameworkElementFactory(typeof(TextBlock)); content.Name = "tx";
        content.SetValue(TextBlock.HorizontalAlignmentProperty, System.Windows.HorizontalAlignment.Center);
        content.SetValue(TextBlock.VerticalAlignmentProperty, System.Windows.VerticalAlignment.Center);
        content.SetBinding(TextBlock.TextProperty, new Binding("Content") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        content.SetBinding(TextBlock.FontFamilyProperty, new Binding("FontFamily") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        content.SetBinding(TextBlock.FontWeightProperty, new Binding("FontWeight") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        content.SetBinding(TextBlock.FontSizeProperty, new Binding("FontSize") { RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent) });
        content.SetValue(TextBlock.ForegroundProperty, Brushes.White);
        root.AppendChild(content);
        template.VisualTree = root;
        SetValue(TemplateProperty, template);
    }
}

我的函数类:

static class Functions
{
    public static Color getLighterShade(Color color)
    {
        float correctionFactor = 0.5f;
        float red = (255 - color.R) * correctionFactor + color.R;
        float green = (255 - color.G) * correctionFactor + color.G;
        float blue = (255 - color.B) * correctionFactor + color.B;
        System.Drawing.Color lighterColor = System.Drawing.Color.FromArgb(color.A, (int)red, (int)green, (int)blue);
        return Color.FromArgb(lighterColor.A, lighterColor.R, lighterColor.G, lighterColor.B);
    }
    public static Color getDarkerShade(Color color)
    {
        System.Drawing.Color c1 = System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B);
        System.Drawing.Color c2 = System.Drawing.Color.FromArgb(c1.A,
            (int)(c1.R * 0.5), (int)(c1.G * 0.5), (int)(c1.B * 0.5));
        return Color.FromArgb(c2.A, c2.R, c2.G, c2.B);
    }
    public static LinearGradientBrush newGradientBrush(params Color[] colors)
    {
        GradientStopCollection gsc = new GradientStopCollection();
        float f = 1f / (float)(colors.Length - 1);
        float y = 0;
        for (int x = 0; x <= colors.Length - 1; x++)
        {
            gsc.Add(new GradientStop(colors[x], y));
            y += f;
        }
        return new LinearGradientBrush(gsc);
    }
}

最后是扩展类:

public static class Extensions
{
    public static Color ToSysDrawCol(this System.Windows.Media.Color col)
    {
        return System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B);
    }
}

使用自定义控件,我想说的应该很清楚。

CCD_ 1和CCD_。在BackgroundBrushProperty的设置中,我根据当前背景的浅色和深色设置了这两种颜色。

现在,正如您所看到的,在MouseDown事件中,我为控件的背景属性设置了动画。但正因为如此,MDBG也再次发生了变化。因此,最终,颜色变得透明。我该如何纠正这种行为?

如何修复设置属性时由于递归而导致的此问题

不要设置MOBG&设置BackgroundBrush时使用MDBG,而不是为两个属性实现get:

public Color MDBG 
{ 
    get
    {
            return  Functions.getDarkerShade((GetValue(BackgroundBrushProperty) as SolidColorBrush).Color);
    }; 
// no set
// set; 
}

如果Functions.getDarkerShade((GetValue(BackgroundBrushProperty) as SolidColorBrush).Color);太慢(我对此表示怀疑),请使用一个可以用作缓存的成员变量Color? _MDBG(当它为null时计算一次,并为后面的每个get返回值)。

在这种情况下,当MOBG1发生变化时(即,不是简单地在设置时,而是在使用与前一个不同的值设置时),您必须实现正确的_MDBG = null;