向Windows窗体控件组添加行为

时间:2010-06-19 04:33:06

标签: c# winforms controls

我正在尝试模仿在文本框上显示标签的Web功能,该文本框显示文本框应包含的值的类型。我可以单独添加事件,但我想知道是否有办法将“行为”添加到一组控件中。

请参阅示例代码:

private void labelFirstName_Click(object sender, EventArgs e)
{
    HideLabelFocusTextBox(labelFirstName, textBoxFirstName);
}

private void HideLabelFocusTextBox(Label LabelToHide, TextBox TextBoxToShow)
{
    LabelToHide.Visible = false;
    TextBoxToShow.Focus();
}

private void textBoxFirstName_Leave(object sender, EventArgs e)
{
    if (String.IsNullOrEmpty(textBoxFirstName.Text))
        labelFirstName.Visible = true;
}

private void textBoxFirstName_Enter(object sender, EventArgs e)
{
    labelFirstName.Visible = false;
}

5 个答案:

答案 0 :(得分:2)

您可以继承文本框控件(编写自己的文本框继承文本框)

是的,我已经考虑过这个问题,我会采取另一种方法:

我会覆盖文本框的绘图处理程序,当文本框不包含任何信息时,将信息字符串绘制到其中。

类似的东西:

using System;
using System.Windows.Forms;
using System.Drawing;

class MyTextBox : TextBox
{
    public MyTextBox()
    {
        SetStyle(ControlStyles.UserPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (string.IsNullOrEmpty(this.Text))
        {
            e.Graphics.DrawString("My info string...", this.Font, System.Drawing.Brushes.Gray, new System.Drawing.PointF(0, 0));
        }
        else
        {
            e.Graphics.DrawString(Text, this.Font, new SolidBrush(this.ForeColor) , new System.Drawing.PointF(0, 0));
        }
    }

    protected override void OnTextChanged(EventArgs e)
    {
        Invalidate();
        base.OnTextChanged(e);
    }
}

答案 1 :(得分:2)

领带行为

您可以使用extension methods将功能/行为更接近TextBox控件。这个简单的解决方案可能会让它感觉更紧密:

// NOTE: first parameter "this TextBox thisText"- these are all extension methods.

static public void AssignLabel(this TextBox thisText, Label companionLabel) {
    thisText.Tag = companionLabel;

    // HOOK UP EVENT AT THIS POINT, WHEN LABEL IS ASSIGNED (.NET 3.x)
    thisText.Leave += (Object sender, EventArgs e) => {
        LeaveMe(thisText); // Invoke method below.
    };
}

static public void FocusText(this TextBox thisText) {
    if (! ReferenceEquals(null, thisText.Tag))
        (Label)thisText.Tag).Visible = false;
    thisText.Focus();
}

static public void LeaveMe(this TextBox thisText) {
    if (String.IsNullOrEmpty(thisText.Text))
        ((Label)thisText.Tag).Visible = true;
}

//etc.

然后使用你的文本框实例:

Label overlay1 = new Label();  // Place these appropriately
Label overlay2 = new Label();  // on top of the text boxes. 
Label overlay3 = new Label();  
TextBox myTextbox1 = new TextBox();
TextBox myTextbox2 = new TextBox();
TextBox myTextbox3 = new TextBox();

// Note: Calling our extension methods directly on the textboxes.
myTextbox1.AssignLabel(overlay1);
myTextbox1.FocusText();
myTextbox1.LeaveMe();

myTextbox2.AssignLabel(overlay2);
myTextbox2.FocusText();
myTextbox2.LeaveMe();

myTextbox3.AssignLabel(overlay3);
myTextbox3.FocusText();
myTextbox3.LeaveMe();
//etc...

如何运作

代码更清晰,适用于您实例化的所有TextBox

它依赖于TextBox类的.Tag property来存储Label引用(因此每个TextBox都知道它的标签),以及.NET 3.x中引入的extension methods允许我们“将”方法“附加”到TextBox类本身,以将您的行为直接绑定到它。

我接受了你的代码并通过调整生成了几乎相同的东西,将其转换为扩展方法,并将Label与文本框相关联。

变异

如果要将相同的方法附加到其他控件(而不仅仅是文本框),请扩展基本Control类本身,如:

static public void LeaveMe(this Control thisControl) { //...

答案 2 :(得分:1)

您始终可以创建执行此操作的用户控件。将TextBox和Label放在控件中,并在用户控件内编写逻辑。这样,该控件的每个实例都会表现相同。

答案 3 :(得分:1)

另一种选择可能是使用Extender Provider。这些基本上允许您在设计时向任何控件添加行为(尽管如果我没记错,这些可能会受到限制)。 ToolTip是一个已在框架中浮动的Extender Provider的示例。我曾经多次使用这些来做一些事情,例如添加支持从资源文件中获取控件的文本值。

答案 4 :(得分:1)

我会将常规文本框子类化并添加属性,这些属性允许您查找关联的标签或直接设置对相关标签的引用。

通常在winform项目中,我在将所有控件添加到表单之前对其进行子类化,因此我可以非常轻松地添加常用功能,而无需在将来更改表单。