【问题标题】:Accesing controls of a FormView, getting Null references访问 FormView 的控件,获取 Null 引用
【发布时间】:2012-08-05 20:02:51
【问题描述】:

我有一个 FormView,我需要访问其中的一些 Div 和其他控件。我的 apsx 代码与此类似:

 <asp:FormView ID="Edit_FV" runat="server" DataKeyNames="IDproceso" DefaultMode="Edit" DataSourceID="SqlDS_Procesos">
            <EditItemTemplate>
                <div id="second_info" runat="server">
                    <div id="second_info_left" runat="server">
                        <div id="alcance" class="report_field" runat="server">
                            <p class="container-title">
                                Alcance:</p>
                            <asp:TextBox ID="TextBox14" runat="server" TextMode="multiline" Width="400px" Height="120px" Text='<%# Bind("alcance") %>' />
                        </div> 
                    </div>
                    <div id="second_info_right" runat="server">
                    <div class="valores-container" id="tipo_ahorro" runat="server">
                        <asp:CheckBox ID="ahorro_state" runat="server" Checked='<%# Bind("tipo_ahorro") %>'  />
                    </div>
                </div>
            </EditItemTemplate>
        </asp:FormView>

现在,假设我想使用 id = ahorro_state 访问 CheckBox,我尝试使用 Edit_FV.FindControl("ahorro_state") 并获得了 Null 引用。我还尝试了Edit_FV.FindControl("MainContent_Edit_FV_ahorro_state"),因为这是在最终 HTML 文档中实际命名 ID 的方式,但我也得到了 Null 引用。当我尝试访问任何 div(ID 为 second_infotipo_ahorro 等)时,也会发生同样的情况。我觉得我犯了一个愚蠢的错误,但我环顾四周并没有找到答案。

有什么办法解决这个问题吗?

编辑:添加了我调用 FindControl 的代码。

我尝试从 Page_Load() 调用 DataBind():

protected void Page_Load(object sender, EventArgs e)
        {

            DataBind();
            if (Edit_FV.CurrentMode == FormViewMode.Edit)
            {
                Control c = Edit_FV.FindControl("ahorro_state");//c is null here.
            }
        }

还尝试设置Edit_FV的OnDataBound属性:OnDataBound="onBound"

   protected void onBound(object sender, EventArgs e)
            {
                if (Edit_FV.CurrentMode == FormViewMode.Edit)
                {
                    ControlCollection a = Edit_FV.Controls;
                    Control c = Edit_FV.FindControl("ahorro_state");//c is null here
                }

            }

【问题讨论】:

  • 您尝试在哪个页面事件中访问控件?
  • 就在Page_Load()中,有什么问题吗?

标签: asp.net webforms


【解决方案1】:

虽然默认模式设置为“编辑”,但在控件被 DataBound 之前,表单视图不会切换到该模式。尝试首先调用DataBind(),然后使用您的元素ID(不是ClientID,如您在第二个示例中尝试的那样)使用FindControl。

请参阅FormView.FindControl(): object reference error,了解将 FindControl 逻辑放置在何处的示例。

编辑:

您的数据源也有可能没有返回任何数据。这将导致 EditItemTemplate 为空,这可能会解释您的空引用错误。在切换到编辑模式之前尝试检查Edit_FV.DataItemCount &gt; 0

【讨论】:

  • 仍然得到空引用。我尝试在 Page_Load() 中调用 DataBind(),并从 FormView 的 OnDataBound 属性中调用所有内容。
  • 你能用调用 FindControl 的代码块更新你的问题吗?
  • 刚刚添加到问题中。
  • 我觉得不错!查看我更新的答案...我认为问题可能出在您的数据源上。
  • 对。当我开始调试时,它没有传递任何参数就进入了一个 URL,所以它正在渲染一个空的 FormView。谢谢!
【解决方案2】:

我在使用“FindControl”时遇到过类似的问题。我找到了一段对我有帮助的代码
a) 递归查找控件,并且
b) 调试语句非常有助于了解为什么我没有找到相关控件。
为了帮助我找到控件,我必须在查找它们时为它们提供 ID 值(如果它们默认没有 ID 值):

    public static class General_ControlExtensions
{
    //From: http://www.devtoolshed.com/content/find-control-templatefield-programmatically
    /// <summary>
    /// recursively finds a child control of the specified parent.
    /// USAGE: 
    /// Control controlToFind = DetailsView1.fn_ReturnControl_givenControlID("txtName");
    /// </summary>
    /// <param name="rootControl"></param>
    /// <param name="ID"></param>
    /// <returns></returns>
    public static Control fn_ReturnControl_givenControlID(this Control rootControl, string ID)
    {
        if (rootControl.ID == ID)
        {
            return rootControl;
        }
        foreach (Control control in rootControl.Controls)
        {

            Debug.WriteLine("FindByID - child.id: " + control.ID);
            Control foundControl = fn_ReturnControl_givenControlID(control, ID);
            if (foundControl != null)
            {
                return foundControl;
            }
        }
        return null;
    }

下面是它的用法示例:

using System.Diagnostics;   // for debug 

TextBox txt_LastName = (TextBox)fv_NewHire_DetailsForm.fn_ReturnControl_givenControlID("INSERT_txt_LastName");

此外,我发现在 'insertitemtemplate' 中的控件前面加上 'INSERT_' 和在 'edititemtemplate' 中的控件前面加上 'EDIT_' 有助于在调试输出中快速区分它们.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    相关资源
    最近更新 更多