简体   繁体   English

第三方控件在WinForms中的单选按钮列表吗?

[英]Third party controls for a radio button list in WinForms?

Are there any controls that can dynamically create a group of radio buttons from a list of objects? 是否有任何控件可以根据对象列表动态创建一组单选按钮? Something similar to the CheckedBoxList control, but with mutually exclusive selection. 类似于CheckedBoxList控件,但具有互斥选择。 This question points out this control doesn't exist natively for WinForms but are there any third party controls that do this? 这个问题指出WinForms本身不存在此控件,但是是否有任何第三方控件可以执行此操作?

Maybe; 也许; But this is easier and better to write yourself, though (unless somebody suggests either a free control or better yet sourcecode you can drop into your project). 但这可以使编写自己更容易,更好(除非有人建议您可以使用免费控件或更好的源代码,否则您可以将其放入项目中)。

A little GUI wisdom (I did not make this up but am too lazy to include references): 一点GUI智慧(我没有弥补这一点,但是太懒了以至于无法包含参考):

If a list of radio buttons will ever have > 7-10 items, use a list box. 如果单选按钮的列表中有> 7-10个项目,请使用列表框。

Of course I gather either you don't have control of that or if you do, won't settle for that answer. 当然,我会收集您可能无法控制的答案,或者您将无法解决该答案。

  • Add a scrollable panel to your form 将可滚动面板添加到表单
  • in code, loop thru your list of objects. 在代码中,遍历对象列表。 Inside the loop: 循环内:
    • Make a new radiobutton 制作一个新的单选按钮
    • set the .top property to the .bottom of the previous one (or 0 if no previous) 将.top属性设置为上一个的.bottom(如果没有,则为0)
    • put a copy of your object in the .Tag property (so you can tell which object was selected) 将对象的副本放在.Tag属性中(这样您就可以知道选择了哪个对象)
    • set the width so you don't get a horizontal scrollbar in your scrollable control 设置宽度,这样您就不会在可滚动控件中获得水平滚动条
    • set the .text appropriately. 适当设置.text。 You may need to truncate to avoid wrapping. 您可能需要截断以避免换行。 If you want to go multiline for lines that wrap, you have to increase the height then, but this would require a lot of gymnastics with control.creategraphics, graphics.MeasureString, and other GDI+ features. 如果要对换行的线进行多行处理,则必须增加高度,但这将需要大量具有control.creategraphics,graphics.MeasureString和其他GDI +功能的体操运动。 See the Bob Powell's GDI+ FAQ. 请参阅Bob Powell的GDI +常见问题解答。
    • add a handler so the checkchanged can be processed (AddHandler MyRB, addressof CC_Sub) 添加一个处理程序,以便可以处理checkchanged(AddHandler MyRB,CC_Sub的地址)
    • add it to the scrollable control 将其添加到滚动控件
  • Add the CC_Sub mentioned above - can get right function signature by adding a radiobutton, putting on the handler for CheckChanged, and deleting radio button 添加上述CC_Sub-通过添加单选按钮,放置CheckChanged的处理程序以及删除单选按钮,可以获得正确的功能签名
  • In this sub, set a form-level variable of type of your class to the tag of the sender (you'll have to do ctypeing) 在此子项中,将类类型的表单级变量设置为发件人的标签(您必须进行ctypeing)
  • When your user clicks OK, return that variable, that is the object picked. 当用户单击“确定”时,返回该变量,即选择的对象。

OK so it looks hard. 好,看起来很难。 So is either squeezing this out of management or doling out cash. 因此,要么将其从管理中挤出来,要么分配现金。

If you want fancier stuff, you can make a usercontrol with labels, checkboxes/radio buttons, etc. in it. 如果您想要更高级的东西,可以在其中添加标签,复选框/单选按钮等的用户控件。 You have to handle selecting/unselecting. 您必须处理选择/取消选择。 Then add the usercontrol to a scrollable panel instead of the radiobutton. 然后,将用户控件而不是单选按钮添加到可滚动面板中。 This provides almost unlimited flexibility. 这提供了几乎无限的灵活性。

Control vendors can't make any money with controls like that. 控件供应商不能用这样的控件赚钱。 Here's some code to get your started: 这是一些入门的代码:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM