【问题标题】:Iterating through textbox controls in a panel C#遍历面板 C# 中的文本框控件
【发布时间】:2010-08-26 22:07:15
【问题描述】:

我见过很多其他人有类似的问题,但我在这里找不到我的逻辑缺陷。任何帮助将不胜感激。

我有一个面板,我添加了许多标签和文本框控件,即:

myPanel.Controls.Add(txtBox);

这些控件是在迭代方法之前调用的方法中创建和添加的。

我想遍历每个文本框并将其 Text 属性用作另一种方法中的参数,但我没有任何运气。这是我的迭代尝试:

public void updateQuestions()
{
    try
    {
        foreach (Control c in editQuestionsPanel.Controls)
        {
            if (c is TextBox)
            {
                TextBox questionTextBox = (TextBox)c;

                string question = questionTextBox.Text;

                writeNewQuestionToTblQuestions(question);
            }
        }
    }
    catch (Exception err)
    {
        Console.WriteLine(err.Message);
    }
}

我遇到的问题是当我到达此 updateQuestions() 方法时,控件不在面板中。以下是所涉及的过程:

单击命令按钮并从数据库中读取问题,为每个问题调用一个方法,该方法将 2 个标签和一个文本框添加到 editQuestionsPanel.Controls。该面板位于 PlaceHolder 中,然后使其可见。

当点击 PlaceHolder 中的按钮时,会调用 updateQuestions() 方法并且 editQuestionsPanel.Controls.Count = 1。由于 DB 中有大约 12 个问题,它应该在 36 个左右。Panel 中的一个控件类型:

System.Web.UI.LiteralControl  

它不包含任何控件。

我确信在生命周期的某个地方,Panel 的控件正在被清除,但我不知道如何逐步完成生命周期。我有一个 Page_load 方法,一旦单击按钮就会调用它,但是一旦单击调用 updateQuestions() 的按钮,editQuestionsPanel.Controls.Count 已经回到 1,因此必须在此之前将其清除但我不知道如何纠正这个...

您可以提供任何帮助来帮助我解决这个问题,我们将不胜感激 - 它杀了我!

【问题讨论】:

  • 是什么不工作?
  • 您的代码对我有用。尝试创建一个完全符合您概述的应用程序,如果它不起作用,请发布整个内容。
  • 附带说明,您应该在此处使用as 而不是is。现在,您将变量c 转换两次。尝试做TextBox questionTextBox = c as TextBox; if (questionTextBox != null) { ... } 这将避免不必要的演员表。
  • 我敢打赌,你有生命周期问题,或者myPanel 不是editQuestionsPanel。要诊断生命周期问题,请附加调试器并在各种生命周期事件(OnInit、OnLoad、OnPreRender、OnRender、事件处理程序等)处检查面板上的控件集合,并特别注意控件集合何时被清除。
  • 我认为是生命周期问题,添加后控制数为37。如何逐步完成这些阶段。如何在 OnInit 的开头插入断点并逐步查看它被清除的位置?

标签: c# asp.net textbox iteration


【解决方案1】:

这只会从集合控件中选择 TextBox 类型的控件。

(与control is TextBox(control as TextBox) != null相同)

如果editQuestionsPanel.Controls中包含控件:

using System.Linq;

IEnumerable<TextBox> textBoxes = editQuestionsPanel.Controls.OfType<TextBox>();    
foreach (TextBox textBox in textBoxes)
{
    // do stuff
}

要选择所有子控件,请使用下一个扩展方法:

public static IEnumerable<T> GetChildControls<T>(this Control control) where T : Control
{
    var children = control.Controls.OfType<T>();
    return children.SelectMany(c => GetChildControls<T>(c)).Concat(children);
}

使用:

IEnumerable<TextBox> textBoxes = editQuestionsPanel.GetChildControls<TextBox>();

【讨论】:

  • 感谢您提供此解决方案 - 这绝对是阅读控件的更好方法。但是,这对我没有用,因为 editQuestionPanel.Controls 中的控件似乎在到达我的代码之前就被清除了。我已经使用覆盖方法逐步完成了 PreInit 和 Init。当控件都在面板中就位时,单击“保存”按钮 - 在 PreInit 阶段,editQuestionsControls.Count = null 并且在 Init 阶段它是 1。它应该是 37。如何阻止控件被清除?
  • @Frank:我认为您需要更多地调查/调试您的代码,以找到面板放弃其子控件的地方。我确定它以编程方式发生在某处
  • @Frank:一种更复杂的解决方案 - 将面板替换为您将覆盖包含子控件的集合类型的面板,仅用于调试 Collection.Controls.Add/Remove/Clear
  • 我刚刚浏览了页面,在每个有意义的步骤中测试了 editQuestionPanel.Controls.Count。添加了控件,直到我的 override OnUnload() 方法结束时,我得到的值为 37。然后,一旦我单击“保存”按钮开始通过控件进行迭代,在 OnInit() 方法上,我得到一个 null 值。所以必须在卸载阶段之后清除控件。很抱歉,我没有完全理解您在上述评论中的解决方案 - 对我有帮助吗?
  • @Frank:哎呀,对不起,有一刻我以为你在谈论 WinForms 控件。因此,当您使用 ASP.NET 时,UpdatePanel 删除其子控件是正常行为,我猜
【解决方案2】:

当您动态添加控件时,您需要在每个请求中执行此操作 - asp.net 不会为您执行此操作!

在 Init 或 Load 阶段添加控件,然后它们填充回发值。

【讨论】:

    【解决方案3】:

    一个经常犯的错误:Container.Controls 仅包含此容器中的第一级子控件。即:PanelA中的TextBox1,PanelB中的PanelA,在PanelB.Controls中取不到TextBox1。

    我的解决办法是写一个扩展方法:

    public static IEnumerable<Control> AllControls(this Control ctl)
    {
       List<Control> collection = new List<Control>();
       if (ctl.HasControls())
       {
           foreach (Control c in ctl.Controls)
           {
                 collection.Add(c);
                 collection = collection.Concat(c.AllControls()).ToList();
           }
       }
       return collection;
    }
    

    现在 TextBox1 位于 PanelB.AllControls() 中。过滤所有类型的控件,使用PanelB.AllControls().OfType&lt;TextBox&gt;()

    【讨论】:

    • 您是对的,但是使用 LINQ 您可以更轻松地完成同样的工作。看我的帖子
    【解决方案4】:

    如果其他答案没有帮助,请尝试编写代码但添加递归性。如果它是 editQuestionsPanel => Panel => Textbox

    ,则您的代码将不起作用

    【讨论】:

      【解决方案5】:

      你可以这样做:

      var questions = from tb in editQuestionsPanel.Controls.OfType<TextBox>()
                      select tb.Text;
      
      foreach(var question in questions)
      {
          writeNewQuestionToTblQuestions(question);
      }
      

      【讨论】:

        【解决方案6】:

        试试这个

                int Count = 0;
                foreach (Control ctr in Panel1.Controls)
                {
                    if (ctr is TextBox)
                        Count++;
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多