Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET add custom properties to winform controls

It would be useful to attach a bunch of custom properties to standard controls in .NET, without creating a set of custom controls.

I heard that its possible with WPF, but does somebody knows a solution for plain winform application?

Why? For example, when a control has the focus and its a TextBox, or a DropDownList or a ComboBox, then I want to paint its backcolor in the custom property I could name: "focusColor"

And of course, I do not want to create custom buttons, combos or dropdown...

like image 783
Didier Levy Avatar asked Apr 29 '11 13:04

Didier Levy


2 Answers

In WPF it is done with attached properties. Although there is no exact equivalent in Windows Form, you can implement an IExtenderProvider to "attach" a custom property to a control. This property can then be used in the designer, like a normal property. See the code provided in this blog post for an example.

Here's an implementation for your "FocusColor" example:

[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);
        }
    }
}

Add this code to your project, compile, and add a FocusColorProvider on your form using the designer. A new FocusColor property should appear on the property grid when you select a control, just set it to the color you want. The control's BackColor will be changed to this color when it takes focus.

like image 89
Thomas Levesque Avatar answered Oct 18 '22 18:10

Thomas Levesque


You can utilize the Tag property of each control to store custom data associated with that control. Create a class MyCustomAttributes and assign objects of that type to MyControl.Tag. This won't work in the designer, of course, only at run time.

As an alternative, you could derive some classes like ExtTextBox from TextBox, ExtDropDownList from DropDrownList etc., having some additional attributes. That is a very simple and painless way of creating custom controls, which might be acceptable in your case, even if you said you don't want such a solution.

like image 2
Doc Brown Avatar answered Oct 18 '22 18:10

Doc Brown