【问题标题】:C# - Add all Input Controls to List<Controls> in TabIndex orderC# - 按 TabIndex 顺序将所有输入控件添加到 List<Controls>
【发布时间】:2015-07-28 17:21:25
【问题描述】:

我有一个 Windows 表单,它只是为了从用户那里获取输入,出于所有意图和目的,它只是一个标签和一个相应的输入框(文本框、复选框、掩码文本框等)。

我以编程方式将所有输入字段置于 TabIndex 顺序中,该顺序最适合以适合其位置的方式循环浏览它们(按标签向下输入每一列,然后到下一列的顶部)。

我正在为其构建此项目的人已规定,每次只允许每个文本框可用一个,因为前一个已填写。这是一种未经验证的粗略方式,但本质上是这样的......

if (String.IsNullOrEmpty(textbox1.Text))
{
    textbox2.Enabled = true
}

所以在这个例子中这对两个文本框来说很好,但是表单上有 28 个不同的输入,所以一系列荒谬的 if 语句只能是最后的手段。

我的想法是将所有输入放在一个列表中,理想情况下与它们的 TabIndexes 的顺序相同。我尝试使用 foreach 循环来做到这一点...

    List<Control> inputsList = new List<Control>();
    public void initialiseControls()
    {
        //control position to insert control into list at specified index
        int cntrlpos = 0;
        //for every control in form
        foreach (Control cntrl in this.Controls)
        {
            //not counting labels (not input fields)
            if (!(cntrl is Label))
            {
                //set list position to equal control's TabIndex
                cntrlpos = cntrl.TabIndex;
                //insert the control into the list at the position reflecting TabIndex
                inputsList.Insert(cntrlpos, cntrl); //<---- Error Occurs

                //ASK TEXTBOX TO OUTPUT LIST POSITION AS TEST
                //foreach (var txtbx in this.Controls.OfType<TextBox>())
                //{
                //    txtbx.Text = Convert.ToString(cntrlpos);
                //}
            }
        }

一旦调用该函数,就会抛出一个异常,指出“索引必须在列表的范围内”。 当我在代码中设置断点时,它显示 cntrlpos 等于 29,这比表单上的 28 个输入控件总数还要多。

我不知道从这里去哪里,如果有人可以就上面的代码提供一些建议,以正确的顺序将控件放入列表中(或者向我指出另一种方法的方向来做这样的事情),那么我将不胜感激。

谢谢, 标记

【问题讨论】:

    标签: c# list controls


    【解决方案1】:

    要列出你的清单,试试这个:

    List<Control> inputList =
        (from Control c in getAllControls(this)
         where c.TabStop
         orderby c.TabIndex
         select c).ToList();
    

    在表单类的其他地方定义方法getAllControls

    IEnumerable<Control> getAllControls(Control parent)
    {
        foreach (Control control in parent.Controls)
        {
            yield return control;
            foreach (Control descendant in getAllControls(control))
                yield return descendant;
        }
    }
    

    (取自Recursive control search with Linq并稍作修改)

    这将使您获得甚至嵌套的控件(例如面板或组框中的控件)。

    您不能只使用 TabIndex 作为列表中的索引,因为即使是标签之类的东西也有标签索引,这会弄乱您的索引。

    【讨论】:

    • .OfType() 可能比Where 更好
    • @Hogan 除了我们需要检查不是标签的元素,而不是的元素。
    • this.Controls 更改为this.Controls.Cast&lt;Control&gt;()。此外,这不会找到嵌套控件,只有那些直接由表单本身包含的控件。
    • @Idle_Mind 感谢您获得所有控件的建议。
    • getAllControls(parent) 更改为 getAllControls(control)。另外,将where !(c is Label) 更改为where c.TabStop。现在您已经看到了用户在点击 Tab 时会访问的控件列表...
    【解决方案2】:

    我认为你把它复杂化了......

    只需使用Control.GetNextControl:

    按子项的 Tab 顺序向前或向后检索下一个控件 控制。

    例如,只有文本框:

        private void textBoxes_TextChanged(object sender, EventArgs e)
        {
            Control ctl = (Control)sender;
            if (!String.IsNullOrEmpty(ctl.Text))
            {
                Control next = this.GetNextControl(ctl, true);
                if (next != null)
                { 
                    next.Enabled = true;
                }
            }
        }
    

    显然,您可能需要在不同的处理程序中对某些其他类型的控件进行稍微复杂的检查,但您仍然只需使用 GetNextControl() 获取下一个控件即可启用。

    【讨论】:

      猜你喜欢
      • 2015-09-07
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      • 1970-01-01
      • 2023-04-05
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多