C#动态创建用户控件按钮点击不起作用

时间:2017-11-09 17:48:47

标签: c# dynamic webforms user-controls placeholder

我有一个页面(company.aspx),当您单击页面上的按钮时,按钮单击事件(btnShowDeptsUserControl_Click)会动态创建用户控件并添加到占位符。页面重新加载并显示用户控件。这很好。

我遇到的问题是,当我单击用户控件本身上的按钮时,不会触发btnEmailDepts_Click事件,但会重新加载主页面(company.aspx)。

我已经读过,解决此问题的一种方法是在Page_Init中创建动态用户控件,但我从主页按钮单击创建用户控件。另外,我没有像通常那样在主页面后面的代码中声明用户控件,但确实有一个放置用户控件的放置器。

我还读过你可以在主页面上添加一个委托给用户控制按钮点击,但是这个例子似乎有这么多必要的代码,我认为必须有更好的方法。< / p>

以下是相关的代码段:

company.aspx:

    <asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>

    <asp:PlaceHolder ID="phUserControls" runat="server"></asp:PlaceHolder>

company.aspx.cs:

    protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
    {
        CreateDeptsUserControl();
    }

    private void CreateDeptsUserControl()
    {
        phUserControls.Controls.Clear();
        var uc = (UserControl)LoadControl("~/controls/ucDepartments.ascx");
        phUserControls.Controls.Add(uc);
    }

ucDepartments.ascx:

    <asp:Button ID="btnEmailDepts" runat="server" Text="Send Email" OnClick="btnEmailDepts_Click" />

ucDepartments.ascx.cs:

    protected void btnEmailDepts_Click(object sender, EventArgs e)
    {
        EmailDepts();  // breakpoint here is never hit
    }

    private void EmailDepts()
    {
        // do something
    }

2 个答案:

答案 0 :(得分:1)

如果您阅读MSDN,您会注意到:

  

但是,添加的控件无法跟上回发数据处理。对于参与回发数据处理(包括验证)的附加控件,必须在Init事件中而不是在Load事件中添加控件。

您正在click事件中添加您的控件,该事件发生在initload事件之后,因此回发将无效。

您可以在CreateDeptsUserControl事件中调用ini功能,但在那里您必须检测自己是否点击了btnShowDeptsUserControl。这并不难,您需要检查提交的值集合,看看是否有btnShowDeptsUserControl的项目。

答案 1 :(得分:1)

只是想发布我做的工作。 Racil Hilan的回答帮助我找到了这个解决方案。我取消了动态用户控件,并使用了aspx中更常见的声明用户控件,但将其设置为Visible =&#34; False&#34;默认情况下。

请注意,主页按钮事件为空。另请注意,用户控件Page_Load事件为空。所有检查都在用户控件OnInit事件中完成,该事件在每个主页面加载时执行。

在用户控件OnInit事件中,我有几个保护条件,检查EVENTTARGET(如果有)导致页面/用户控件加载。如果EVENTTARGET(控件ID)是主页按钮的那个,则执行将继续并将调用LoadSomeData()以及设置用户控件Visible = true。否则,如果任一保护条件的计算结果为false,则退出并且不会加载用户控件,因此不会浪费数据库/服务调用。

company.aspx:

    <asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>

    <uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />

company.aspx.cs:

    protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
    {
        // empty, just need the event for inspection later in user control OnInit event.
    }

ucDepartments.ascx:

    <asp:Button ID="btnEmailDepts" runat="server" Text="Send Email" OnClick="btnEmailDepts_Click" />

ucDepartments.ascx.cs:

    protected override void OnInit(EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(Request.Params["__EVENTTARGET"]))
            return;

        var controlName = Request.Params["__EVENTTARGET"];
        if (controlName != "btnShowDeptsUserControl")
            return;

        LoadSomeData();  // call method to load the user control
        this.Visible = true;
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        // empty
    }

    private void LoadSomeData()
    {
        // get data from database
        // load table / gridview / etc
        // make service call
    }

    protected void btnEmailDepts_Click(object sender, EventArgs e)
    {
        EmailDepts();  // this event is now executed when the button is clicked
    }

    private void EmailDepts()
    {
        // do something
    }

包含在回发后滚动到用户控件的jquery的变体:

在主页面按钮单击事件中,您还可以执行类似以下操作:将隐藏的var设置为可在主页doc上检查的值,以便执行一些jquery操作,例如将用户控件滚动到视图中,如果它远在页面下方(我在当前任务中实际执行的操作)。

在单击主页面按钮后,这不仅会将现在加载的用户控件滚动到视图中,还会注意setupDepts()中的代码。我隐藏了执行回发的asp按钮来加载用户控件,并显示一个常规的html按钮。它们看起来都一样(都说Show Depts),但点击时常规的html按钮会触发jquery来切换包含用户控件的div关闭,再次点击,它会打开,再次点击它会关闭等等。

这样,您只需在单击主页按钮时加载一次用户控件(使db / service调用一次),然后可以在随后单击备用按钮时切换显示或隐藏它。这种方法可以与多个按钮或链接一起使用,只要它们都具有相同的类ID。例如,您可能在页面顶部有一个Show Depts按钮/链接,在页面底部有另一个按钮/链接,这是我当前任务中的情况。

company.aspx:

    <asp:Button id="btnShowDeptsUserControl" runat="server" class="btnShowDepts" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
    <button class="btnToggleDepts" style="display: none;">Show Depts</button>

   <div id="divShowDepts" style="display: none;">
       <asp:HiddenField runat="server" id="hdnShowDepts"/>
       <uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />
   </div>

<script language="javascript" type="text/javascript">
    $(function () {
        toggleDeptsUserControl();
        if ($('#<%=hdnShowDepts.ClientID%>').val() === "show")
            setupDepts();
    });

    function setupDepts() {
        $('.btnShowDeptsUserControl').hide();
        $('.btnToggleDeptsUserControl').show();
        scrollToDepts();
    }

    function scrollToDepts() {
        $('#divShowDepts').toggle(700, function () {
            if ($(this).is(":visible")) {
                $('html, body').animate({ scrollTop: ($(this).offset().top) }, 'slow');
            }
        });
    }

    function toggleDeptsUserControl() {
        $('.btnToggleDeptsUserControl').on('click', function (event) {
            event.preventDefault();
            scrollToDepts();
        });
    }
</script>

company.aspx.cs:

    protected void btnShowDeptsUserControl_Click(object sender, EventArgs e)
    {
        hdnShowDepts.Value = "show";
    }