Сторонние элементы управления для списка переключателей в WinForms? - PullRequest
1 голос
/ 04 августа 2010

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

Ответы [ 2 ]

3 голосов
/ 04 августа 2010

Поставщики контрольных устройств не могут зарабатывать деньги с такими элементами управления. Вот некоторый код для начала работы:

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

class RadioList : ListBox {
    public event EventHandler SelectedOptionChanged;

    public RadioList() {
        this.DrawMode = DrawMode.OwnerDrawFixed;
        this.ItemHeight += 2;
    }
    public int SelectedOption {
        // Current item with the selected radio button
        get { return mSelectedOption; }
        set { 
            if (value != mSelectedOption) {
                Invalidate(GetItemRectangle(mSelectedOption));
                mSelectedOption = value; 
                OnSelectedOptionChanged(EventArgs.Empty);
                Invalidate(GetItemRectangle(value));
            }
        }
    }
    protected virtual void OnSelectedOptionChanged(EventArgs e) {
        // Raise SelectOptionChanged event
        EventHandler handler = this.SelectedOptionChanged;
        if (handler != null) handler(this, e);
    }
    protected override void OnDrawItem(DrawItemEventArgs e) {
        // Draw item with radio button
        using (var br = new SolidBrush(this.BackColor))
            e.Graphics.FillRectangle(br, e.Bounds);
        if (e.Index < this.Items.Count) {
            Rectangle rc = new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Height, e.Bounds.Height);
            ControlPaint.DrawRadioButton(e.Graphics, rc,
                e.Index == SelectedOption ? ButtonState.Checked : ButtonState.Normal);
            rc = new Rectangle(rc.Right, e.Bounds.Top, e.Bounds.Width - rc.Right, e.Bounds.Height);
            TextRenderer.DrawText(e.Graphics, this.Items[e.Index].ToString(), this.Font, rc, this.ForeColor, TextFormatFlags.Left);
        }
        if ((e.State & DrawItemState.Focus) != DrawItemState.None) e.DrawFocusRectangle();
    }
    protected override void OnMouseUp(MouseEventArgs e) {
        // Detect clicks on the radio button
        int index = this.IndexFromPoint(e.Location);
        if (index >= 0 && e.X < this.ItemHeight) SelectedOption = index;
        base.OnMouseUp(e);
    }
    protected override void OnKeyDown(KeyEventArgs e) {
        // Turn on option with space bar
        if (e.KeyData == Keys.Space && this.SelectedIndex >= 0) SelectedOption = this.SelectedIndex;
        base.OnKeyDown(e);
    }
    private int mSelectedOption;
}
3 голосов
/ 04 августа 2010

Может быть; Но это проще и лучше написать самостоятельно (если кто-то не предложит либо бесплатный элемент управления, либо лучший исходный код, который вы можете добавить в свой проект).

Немного мудрости GUI (я не придумал это, но мне лень включать ссылки):

Если список переключателей когда-либо будет содержать> 7-10 элементов, используйте список.

Конечно, я понимаю, что либо вы не контролируете это, либо, если вы это сделаете, не согласитесь с этим ответом.

  • Добавьте прокручиваемую панель к вашей форме
  • в коде, проходите через ваш список объектов. Внутри цикла:
    • Создать новую радиокнопку
    • установить свойство .top равным .bottom предыдущего (или 0, если не было предыдущего)
    • поместите копию вашего объекта в свойство .Tag (чтобы вы могли сказать, какой объект был выбран)
    • установить ширину, чтобы вы не получали горизонтальную полосу прокрутки в элементе прокрутки
    • установить .text соответствующим образом. Возможно, вам придется усечь, чтобы избежать переноса. Если вы хотите использовать многострочные линии для переноса, вам нужно увеличить высоту, но для этого потребуется много гимнастики с control.creategraphics, graphics.MeasureString и другими функциями GDI +. См. Часто задаваемые вопросы Боба Пауэлла по GDI +.
    • добавить обработчик, чтобы проверенные данные могли быть обработаны (AddHandler MyRB, address of CC_Sub)
    • добавить его в прокручиваемый элемент управления
  • Добавьте упомянутый выше CC_Sub - можете получить правильную сигнатуру функции, добавив радиокнопку, включив обработчик для CheckChanged и удалив радиокнопку
  • В этом подпрограмме установите переменную типа вашего класса на уровне формы для тега отправителя (вам придется выполнить ввод с клавиатуры)
  • Когда ваш пользователь нажимает кнопку ОК, возвращайте эту переменную, то есть выбранный объект.

ОК, это выглядит сложно. То же самое можно сказать, что выжимаете это из управления или расплачиваетесь наличными.

Если вам нужны более интересные вещи, вы можете создать пользовательский контроль с ярлыками, флажками / переключателями и т. Д. Вы должны обрабатывать выбор / отмена выбора. Затем добавьте пользовательский контроль на прокручиваемую панель вместо радиокнопки. Это обеспечивает практически неограниченную гибкость.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...