User
User

Reputation: 66111

WinForms: Is there a concept of associating a label with a textbox?

I'm using Visual Studio 2010 with C#. Is there a concept in Windows Forms development of somehow linking a label with is text box? Something so that they move together as a unit? In the ASP.NET world, there is the AssociatedControlId property of the label control. I also think I remember MS Access form designer having some way of associating (or linking) labels with controls. Does this feature even exist in Visual Studio world?

If not, how do you group labels with controls such that if you move a text box you don't have to manually move the label also?

Upvotes: 27

Views: 45519

Answers (9)

DigAtRandom
DigAtRandom

Reputation: 49

ReWrite: When this answer was originally posted, the concept was to bind a label to a TextBox as the label's parent. The hope was that the label's visibility would change with that of the TextBox. And this thought may be a departure from what the OP was seeking to solve.

Since a texbox as parent to a label doesn't work that way is what probably earned the downvote.

In the end adding a label and TextBox to a Panel control allows both to change by changing the panel. Consequently, I defer to the other posts outlined above for keeping controls together for positioning on a form. Fooling around with adjustments to the custom control size is another challenge to overcome.

Another Edit it bears mention that user controls raise a difficulty with data Binding for all elements on a form. Solving that problem is a subject for other posts.

Upvotes: -1

user10223479
user10223479

Reputation: 25

You can used taborder and mnemonic character to achive this. Eg:

Say we have a form with a label and a textbox (among other controls).

The label has Text = "&Name" TabIndex = 5

The textbox has TabIndex = 6

If the user presses Alt-N, focus will first try to go to the label (due to the mnemonic &N ). Labels cannot get focus, so focus is attempted on the next control in the tab order (ie the textbox) where it succeeds.

BTW if the next control is another control that cannot get focus, it keeps going through the tab sequence until it finds one that can get focus. It does this until it hits the first control again, where it gives up.

Upvotes: 1

IlPADlI
IlPADlI

Reputation: 2033

This is my solution, using a TableLayoutPanel to place label and input control,

Presetted some useful properties:

  • Auto size label by content
  • Label margin top for vertical-align:middle like style
  • Fill remain space by input control

Preview

preview

The code may need further wrap

internal class TextBoxField : TableLayoutPanel
{
    private readonly TextBox _textBox;

    public string Text
    {
        get => _textBox.Text;
        set => _textBox.Text = value;
    }

    public TextBoxField(string labelText)
    {
        var label = new Label { Text = labelText, AutoSize = true };
        var labelMargin = label.Margin;
        labelMargin.Top = 8;
        label.Margin = labelMargin;
        _textBox = new TextBox { Dock = DockStyle.Fill };

        AutoSize = true;

        ColumnCount = 2;
        RowCount = 1;
        ColumnStyles.Add(new ColumnStyle());
        ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
        RowStyles.Add(new RowStyle());
        Controls.Add(label, 0, 0);
        Controls.Add(_textBox, 1, 0);
    }
}

internal class DateTimePickerField : TableLayoutPanel
{
    private readonly DateTimePicker _dateTimePicker;

    public DateTime Value
    {
        get => _dateTimePicker.Value;
        set => _dateTimePicker.Value = value;
    }

    public DateTimePickerField(string labelText)
    {
        var label = new Label { Text = labelText, AutoSize = true };
        var labelMargin = label.Margin;
        labelMargin.Top = 8;
        label.Margin = labelMargin;
        _dateTimePicker = new DateTimePicker { Dock = DockStyle.Fill };

        AutoSize = true;

        ColumnCount = 2;
        RowCount = 1;
        ColumnStyles.Add(new ColumnStyle());
        ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
        RowStyles.Add(new RowStyle());
        Controls.Add(label, 0, 0);
        Controls.Add(_dateTimePicker, 1, 0);
    }
}

Useage:

var frm = new Form
{
    AutoSize = true,
    StartPosition = FormStartPosition.CenterParent,
    Text = "Assoc Device",
};

var txtGpsCode = new TextBoxField("GpsCode") { Dock = DockStyle.Bottom, TabIndex = 1 };
var dtp = new DateTimePickerField("Expire date") { Dock = DockStyle.Bottom, TabIndex = 2 };
var button = new Button { Text = "OK", DialogResult = DialogResult.OK, Dock = DockStyle.Bottom };

frm.Controls.Add(txtGpsCode);
frm.Controls.Add(dtp);
frm.Controls.Add(button);

frm.AcceptButton = button;

frm.Height = 0;

frm.ShowDialog();

Upvotes: 1

Henrique
Henrique

Reputation: 610

You can use extension methods to do it, follow example:

Private associatedLabels As New Dictionary(Of Control, Label)    
<Extension()>
Public Sub AssociateLabel(ByVal control As Control, ByVal label As Label)
    If (Not associatedLabels.ContainsKey(control)) Then
        associatedLabels.Add(control, label)
    End If
End Sub

<Extension()>
Public Function GetAssociatedLabel(ByVal control As Control) As Label
    If (associatedLabels.ContainsKey(control)) Then
        Return associatedLabels(control)
    Else
        Throw New Exception("There is no associated label")
    End If
End Function

Upvotes: 0

dharmatech
dharmatech

Reputation: 9547

There doesn't appear to be a built in one. You can roll your own Field class though. Below is a complete example.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace FieldClassTest
{
    class Field : FlowLayoutPanel
    {
        public Label label;
        public TextBox text_box;

        public Field(string label_text)
            : base()
        {
            AutoSize = true;

            label = new Label();
            label.Text = label_text;
            label.AutoSize = true;
            label.Anchor = AnchorStyles.Left;
            label.TextAlign = ContentAlignment.MiddleLeft;

            Controls.Add(label);

            text_box = new TextBox();

            Controls.Add(text_box);
        }
    }

    static class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var form = new Form();

            var panel = new FlowLayoutPanel();
            panel.FlowDirection = FlowDirection.TopDown;
            panel.Dock = DockStyle.Fill;

            var first_name = new Field("First Name");
            panel.Controls.Add(first_name);

            var last_name = new Field("Last Name");
            panel.Controls.Add(last_name);

            form.Controls.Add(panel);

            Application.Run(form);
        }
    }
}

Here's what the example program looks like on my system:

enter image description here

Upvotes: 25

V4Vendetta
V4Vendetta

Reputation: 38230

i think the best bet would be to use a GroupBox.

Upvotes: -1

Brian
Brian

Reputation: 38035

I 2nd @Neils answer of just creating a user control with a textbox in it. The panel can be used to group controls, but it can be pretty tedious if you have a lot of controls on the form.

If you want to support more than just textboxes, WinForms allows you to create your own designer. If you inherit your designer from the ParentControlDesigner class, you can drop any control you want into your custom label control.

Upvotes: 1

Devendra D. Chavan
Devendra D. Chavan

Reputation: 9031

If you want to group labels with other controls (or group controls in general), then use the System.Windows.Forms.Panel control. The specific purpose of the Panel control is to group collections of controls.

More information Panel Class (System.Windows.Forms)

If you want a higher degree of control (rather than using a Panel), then you could create a UserControl, that encapsulates a Label and a Control.

Upvotes: 1

Neil
Neil

Reputation: 1633

No there is not - at least with the out of the box controls. If you want this you could achieve it with a user control.

In general the winforms is not line driven in the same way as HTML is.

Upvotes: 11

Related Questions