【问题标题】:"Unable to cast object" while looping through programatically created textboxes循环通过编程创建的文本框时“无法投射对象”
【发布时间】:2012-11-27 16:47:48
【问题描述】:

我有一些动态创建的文本框——

int i = 1;
while (reader.Read())
{
    System.Web.UI.WebControls.TextBox textBox = new System.Web.UI.WebControls.TextBox();
    textBox.ID = reader["field_id"].ToString();
    textBox.Enabled = false;
    HtmlGenericControl div = new HtmlGenericControl("div");

    if(i%2 != 0)
        div.Attributes.Add("style", "margin-right:120px;padding-bottom:20px;");

    if (i % 2 == 0)
        div.Attributes.Add("style", "padding-bottom:20px;");

    div.Attributes.Add("class", "inline fourcol");
    div.InnerHtml = "<label>" + reader["field"] + "</label>"; 
    div.Controls.Add(textBox);
    panelId.Controls.Add(div);
    textBox.Text = reader["field_value"].ToString();
    ++i;
}

这很好用(至少我确定 - 他们会显示他们应该如何显示)。但是当我尝试遍历它们以启用它们或获取它们的值时,我得到一个“无法将'System.Web.UI.LiteralControl'类型的对象转换为'System.Web.UI.WebControls'。文本框'。“错误。

这就是我一直在尝试的方式--

public void EditPanel(System.Web.UI.WebControls.Panel panel)
{
    foreach (System.Web.UI.WebControls.TextBox t in panel.Controls)
    {
        t.Enabled = true;
    }
}

谢谢!

【问题讨论】:

  • 这意味着在您的 panel.Controls 中有一个不是 TextBox 的控件。

标签: c# asp.net .net c#-4.0


【解决方案1】:

您正在循环访问panel.Controls,它将循环访问面板中的每个控件。这不一定与循环遍历您添加的所有内容相同。如果您开始时面板中存在其他内容,那么您最终也会得到它。

你可能想要的是这个:

foreach (var t in panel.Controls.OfType<System.Web.UI.WebControls.TextBox>())
{
    t.Enabled = true;
}

【讨论】:

  • 我不再收到错误消息。谢谢。但现在这只是发现了更多问题。因为文本框是在页面加载时创建的,所以在调用带有编辑功能的按钮单击时它们不会做任何事情。如果创建函数被移动到 if(!IsPostback) 中,当页面重新加载时它们就不存在了。还是谢谢。
  • @smarble 听起来像是提出了一个新问题!
  • 一个问题是没有在 Page_Init 中创建控件。另外,我需要更深入地控制一个。面板有文本框所在的 html div - 这就是为什么我无法对它们做任何事情。
【解决方案2】:

您将每个文本框放在一个“div”控件中,即HtmlGenericControl,然后放在面板控件中。所以首先你必须在panelId.Controls里面搜索HtmlGenericControl

可能对您有所帮助的示例代码:

public void EditPanel(System.Web.UI.WebControls.Panel panel)
{
    foreach (Control c in panelId.Controls)
            {
                if (c is HtmlGenericControl)
                {
                    foreach (var textbox in c.Controls.OfType<TextBox>()) //ofType returns IEnumerable<TextBox>
                        textbox.Enabled = true;
                }
            }
} 

【讨论】:

  • 起初我认为 YYY(以及其他所有人的)的答案是有效的,因为我不再收到投射错误,但文本框没有启用。这是因为它们在各自的 div 中,无论出于何种原因,我都没有看到。
【解决方案3】:

您的Panel 中有一个控件,它不是TextBox,并且无法转换为它。您应该在循环之前放置一个断点,并在调试模式下检查panel.Control 集合内容。

如果您不在foreach 循环中指定类型并自己进行安全转换,则可以避免此问题。

foreach (var t in panel.Controls)
{
    var textbox = t as System.Web.UI.WebControls.TextBox;
    if(textbox != null)
    {               
        textbox.Enabled = true;
    }
}

【讨论】:

    【解决方案4】:

    你应该检查控件是否是文本框

    public void EditPanel(System.Web.UI.WebControls.Panel panel)
    {
        foreach (var t in panel.Controls)
        {
            if (t is System.Web.UI.WebControls.TextBox)
                ((System.Web.UI.WebControls.TextBox)t).Enabled = true;
        }
    }
    

    【讨论】:

      【解决方案5】:

      Controls 集合将包含面板中所有控件的集合——不仅仅是文本框。您可以遍历所有控件并使用as 运算符执行类型转换。如果类型转换成功,那么您可以启用文本框。

      public void EditPanel(System.Web.UI.WebControls.Panel panel)
      {
          foreach (var control t in panel.Controls)
          {
              System.Web.UI.WebControls.TextBox textBox = control as System.Web.UI.WebControls.TextBox;
              if (textBox != null)
              {
                  control.Enabled = true;
              }    
          }
      }
      

      【讨论】:

        【解决方案6】:

        您将文本框添加到 div 元素,并将 div 元素添加到面板。因此您需要选择面板中的控件,然后找到文本框。

        foreach (var t in panel.Controls.Cast<Control>().SelectMany(c => c.Controls))
        {
            if (t is TextBox == false) continue;
        
            ((TextBox)t).Enabled = true;
        }
        

        【讨论】:

        • 这是为你编译的吗?当我在我的 ghetto 测试项目中尝试它时,我得到了 System.Web.UI.ControlCollection' does not contain a definition for 'SelectMany' and no extension method 'SelectMany' accepting a first argument of type 'System.Web.UI.ControlCollection' could be found (are you missing a using directive or an assembly reference?) 不过,我完全有可能顶了一些东西。
        • @YYY 你有引用 System.Linq 吗?
        • @frinkenstein789 当然可以!这就是我能够在自己的答案中使用OfType 方法的原因。
        • 该属性为ControlsCollection类型,只实现了OfTypeCastAsParallelAsQueryable方法,因为它没有实现IEnumerable&lt;T&gt;接口,只有较旧的IEnumerable
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-27
        • 1970-01-01
        • 1970-01-01
        • 2014-11-27
        • 2013-09-04
        • 1970-01-01
        相关资源
        最近更新 更多