.NET向Winform控件添加自定义属性

6

在.NET中,将自定义属性附加到标准控件而不创建一组自定义控件会很有用。

我听说WPF可以做到这一点,但是否有解决方案适用于普通的winform应用程序呢?

为什么?例如,当控件具有焦点时,它是一个TextBox、DropDownList或ComboBox,那么我希望将其BackColor绘制成我可以命名为“focusColor”的自定义属性。

当然,我不想创建自定义按钮、下拉框或组合框...

2个回答

10
在WPF中,这是通过附加属性实现的。虽然在Windows Form中没有精确的等效物,但您可以实现IExtenderProvider来将自定义属性“附加”到控件上。然后可以在设计器中使用此属性,就像普通属性一样。有关示例,请参见此博客文章中提供的代码。
以下是“FocusColor”示例的实现:
[ProvideProperty("FocusColor", typeof(Control))]
public class FocusColorProvider : Component, IExtenderProvider
{
    private readonly Dictionary<IntPtr, Color> _focusColors;
    private readonly Dictionary<IntPtr, Color> _backColors;

    public FocusColorProvider()
    {
        _focusColors = new Dictionary<IntPtr, Color>();
        _backColors = new Dictionary<IntPtr, Color>();
    }

    public bool CanExtend(object extendee)
    {
        return (extendee is Control);
    }

    public Color GetFocusColor(Control ctl)
    {
        Color color;
        if (_focusColors.TryGetValue(ctl.Handle, out color))
        {
            return color;
        }
        return ctl.BackColor;
    }

    public void SetFocusColor(Control ctl, Color color)
    {
        Color backColor;
        if (!_backColors.TryGetValue(ctl.Handle, out backColor))
        {
            backColor = ctl.BackColor;
        }

        // Same color as BackColor, disable the behavior
        if (color == backColor)
        {
            RemoveFocusColor(ctl);
            ctl.LostFocus -= ctl_LostFocus;
            ctl.GotFocus -= ctl_GotFocus;
            _focusColors.Remove(ctl.Handle);
        }
        else
        {
            _focusColors[ctl.Handle] = color;
            if (ctl.Focused)
                ApplyFocusColor(ctl);
            ctl.LostFocus += ctl_LostFocus;
            ctl.GotFocus += ctl_GotFocus;
        }
    }

    void ctl_GotFocus(object sender, EventArgs e)
    {
        ApplyFocusColor((Control)sender);
    }

    void ctl_LostFocus(object sender, EventArgs e)
    {
        RemoveFocusColor((Control)sender);
    }

    void ApplyFocusColor(Control ctl)
    {
        _backColors[ctl.Handle] = ctl.BackColor;
        ctl.BackColor = GetFocusColor(ctl);
    }

    void RemoveFocusColor(Control ctl)
    {
        Color color;
        if (_backColors.TryGetValue(ctl.Handle, out color))
        {
            ctl.BackColor = color;
            _backColors.Remove(ctl.Handle);
        }
    }
}

将以下代码添加到您的项目中,编译并使用设计器在表单上添加一个FocusColorProvider。当您选择控件时,属性网格上将出现一个新的FocusColor属性,只需将其设置为所需的颜色即可。当控件获得焦点时,其背景颜色将更改为此颜色。

哇!非常漂亮,谢谢Thomas :-) - Didier Levy
Thomas,需要更多的帮助!...当我将您的代码复制/粘贴到一个新项目中时,我必须添加“using System.ComponentModel;”,并且我还有两个错误显示为:“未找到控件的类型或名称空间”和“颜色”同样。无法编译该类 :-( - Didier Levy
哎呀,搞定了,只需要添加 using system.drawing 和 system.windows.forms。 - Didier Levy

3
您可以利用每个控件的Tag属性来存储与该控件相关联的自定义数据。创建一个名为MyCustomAttributes的类,并将该类型的对象分配给MyControl.Tag。当然,在设计时这是行不通的,只能在运行时使用。
作为替代方案,您可以从TextBox派生一些类,如ExtTextBox,从DropDownList派生ExtDropDownList等,具有一些附加属性。这是创建自定义控件的非常简单和无痛的方式,在您的情况下可能是可接受的,即使您说您不想使用这种解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接