WinForms: есть ли концепция связывания метки с текстовым полем? - PullRequest
19 голосов
/ 19 января 2011

Я использую Visual Studio 2010 с C #. Есть ли в Windows Forms концепция, как связать ярлык с текстовым полем? Что-то, чтобы они двигались вместе как единое целое? В мире ASP.NET есть свойство AssociatedControlId элемента управления меткой. Мне также кажется, что я помню дизайнера MS Access, у которого был какой-то способ связывать (или связывать) метки с элементами управления. Эта функция вообще существует в мире Visual Studio?

Если нет, то как сгруппировать ярлыки с элементами управления, чтобы при перемещении текстового поля вам также не приходилось перемещать ярлык вручную?

Ответы [ 7 ]

23 голосов
/ 19 ноября 2011

Кажется, что нет встроенного. Вы можете бросить свой собственный класс Field. Ниже приведен полный пример.

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

Вот как выглядит пример программы на моей системе:

enter image description here

9 голосов
/ 19 января 2011

Нет, нет - по крайней мере, из коробки управления.Если вы хотите этого, вы можете достичь этого с помощью пользовательского элемента управления.

Обычно winforms не управляются линиями так же, как HTML.

1 голос
/ 19 января 2011

Я 2-й @Neils ответ только на создание пользовательского элемента управления с текстовым полем в нем. Панель можно использовать для группировки элементов управления, но она может быть довольно утомительной, если в форме много элементов управления.

Если вы хотите поддерживать больше, чем просто текстовые поля, WinForms позволяет вам создать свой собственный дизайнер. Если вы унаследовали свой дизайнер от класса ParentControlDesigner , вы можете добавить любой элемент управления в свой пользовательский элемент управления меткой.

1 голос
/ 19 января 2011

Если вы хотите сгруппировать метки с другими элементами управления (или сгруппировать элементы управления в целом), используйте элемент управления System.Windows.Forms.Panel. Конкретное назначение панели управления - group collections of controls.

Дополнительная информация Класс панели (System.Windows.Forms)

Если вам нужна более высокая степень контроля (нежели использование Panel), тогда вы можете создать UserControl, который включает в себя Label и Control.

0 голосов
/ 25 января 2018

Это мое решение, использующее TableLayoutPanel для размещения метки и управления вводом,

Предустановлены некоторые полезные свойства:

  • Метка автоматического размера по содержимому
  • Верх надписи для поля выравнивание по вертикали: середина как стиль
  • Заполнить оставшееся пространство с помощью ввода

Предварительный просмотр

preview

Код может нуждаться в дальнейшей переносе

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();
0 голосов
/ 07 марта 2013

Вы можете использовать методы расширения для этого, следуйте примеру:

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
0 голосов
/ 19 января 2011

Я думаю, что лучше всего было бы использовать GroupBox.

...