简体   繁体   English

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

[英]C# dynamically created user control button click not working

I have a page (company.aspx) that when you click a button on the page the button click event (btnShowDeptsUserControl_Click) dynamically creates a user control and adds to a placeholder. 我有一个页面(company.aspx),当您单击页面上的按钮时,按钮单击事件(btnShowDeptsUserControl_Click)动态创建用户控件并将其添加到占位符。 The page reloads with the user control displayed. 页面将重新加载,并显示用户控件。 That works fine. 很好

The issue I am having is that when I click the button on the user control itself, the btnEmailDepts_Click event is not fired, but the main page (company.aspx) is reloaded. 我遇到的问题是,当我单击用户控件本身上的按钮时,不会触发btnEmailDepts_Click事件,但是会重新加载主页(company.aspx)。

I have read that one way to resolve this is to create the dynamic user control in Page_Init, but I am creating the user control from the main page button click. 我已经读过一种解决此问题的方法是在Page_Init中创建动态用户控件,但是我正在通过单击主页按钮来创建用户控件。 Also, I am not declaring the user control in the code behind of the main page as you would normally, but do have a placehoder within which the user control is added. 另外,我没有像通常那样在主页后面的代码中声明用户控件,但是确实有一个其中添加了用户控件的放置器。

I have also read that you can add a delegate to the main page for the user control button click, but the example seemed to have so much necessary code for such a simple thing that I figured there must be a better way. 我还读到您可以在用户控件按钮单击的主页上添加一个委托,但是该示例似乎对这么简单的事情有太多必要的代码,以至于我认为必须有更好的方法。

Here are the relevant code snippets: 以下是相关的代码段:

company.aspx: 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: 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: ucDepartments.ascx:

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

ucDepartments.ascx.cs: ucDepartments.ascx.cs:

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

    private void EmailDepts()
    {
        // do something
    }

If you read the MSDN , you will notice: 如果您阅读MSDN ,则会注意到:

However, the added control does not catch up with postback data processing. 但是,添加的控件不能赶上回发数据处理。 For an added control to participate in postback data processing, including validation, the control must be added in the Init event rather than in the Load event. 为了使添加的控件参与回发数据处理(包括验证),必须在Init事件中而不是Load事件中添加该控件。

You are adding your control in the click event which happens after both init and load events, so the postback will not work. 您将控件添加到在initload事件之后发生的click事件中,因此回发将不起作用。

You can call your CreateDeptsUserControl function in the ini event, but there you will have to detect if the btnShowDeptsUserControl was clicked by yourself. 您可以在ini事件中调用CreateDeptsUserControl函数,但在那里您将必须检测btnShowDeptsUserControl是否被您自己单击。 It's not hard, you will need to check the submitted values collection and see if there is an item for btnShowDeptsUserControl . 这并不难,您将需要检查已提交的值集合,并查看btnShowDeptsUserControl是否存在一个项目。

Just wanted to post what I did to make this work. 只是想发布我所做的这项工作。 Racil Hilan's answer helped me to arrive at this solution. Racil Hilan的回答帮助我得出了这个解决方案。 I did away with the dynamic user control, and went with the more common declared user control in the aspx, but set it to Visible="False" by default. 我取消了动态用户控件,并使用了aspx中更常见的声明用户控件,但默认情况下将其设置为Visible =“ False”。

Notice that the main page button event is empty. 请注意,主页按钮事件为空。 Also notice that the user control Page_Load event is empty. 还要注意,用户控件Page_Load事件为空。 All the checking is done in the user control OnInit event, which is executed with each main page load. 所有检查都在用户控件OnInit事件中完成,该事件在每次加载主页时执行。

In the user control OnInit event I have a couple guard conditions that check to see what EVENTTARGET, if any, caused the page / user control to load. 在用户控件的OnInit事件中,我有几个保护条件,检查是否有什么EVENTTARGET(如果有的话)导致页面/用户控件加载。 If the EVENTTARGET (control ID) is that of the main page button, then execution will continue and will call LoadSomeData() as well as set the user control Visible = true. 如果EVENTTARGET(控件ID)是主页按钮的控件,则执行将继续并调用LoadSomeData()并将用户控件设置为Visible = true。 Otherwise, if either guard condition evaluates as false, we exit and the user control does not get loaded, so no wasted db / service calls. 否则,如果任一保护条件的评估结果为false,我们将退出并且不会加载用户控件,因此不会浪费db / service调用。

company.aspx: 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: 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: ucDepartments.ascx:

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

ucDepartments.ascx.cs: 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
    }

Variation that includes jquery to scroll to user control after postback: 回传后包含jquery滚动到用户控件的变体:

In the main page button click event you can also do something like set a hidden var to a value that can be inspected on main page doc ready to do some jquery stuff, such as scrolling the user control into view if it is far down the page (which I am actually doing in my current task). 在主页按钮单击事件中,您还可以执行类似的操作,例如将隐藏的var设置为可以在主页doc上检查的值,以准备进行一些jquery的操作,例如将用户控件滚动到视图中(如果该控件位于页面下方) (实际上是我当前的任务)。

Not only will this scroll the now loaded user control into view after clicking the main page button, but notice the code in setupDepts(). 单击主页按钮后,这不仅会将当前加载的用户控件滚动到视图中,而且还会注意到setupDepts()中的代码。 I hide the asp button that does a postback to load the user control, and show a regular html button. 我隐藏了执行回发以加载用户控件的asp按钮,并显示了常规的html按钮。 They both look the same (both say Show Depts), but the regular html button, when clicked, will fire jquery to toggle the div that contains the user control to close, click again, it will open, click again it will close, etc. 它们看起来都一样(都说Show Depts),但是单击常规html按钮时,将触发jquery切换包含用户控件的div,使其关闭,再次单击,它将打开,再次单击,它将关闭,等等。 。

This is so that you only load the user control once (make db / service calls once) when the main page button is clicked, and then can toggle show or hide it with subsequent clicks of the alternate button. 这样一来,当单击主页按钮时,您只加载一次用户控件(使数据库/服务调用一次),然后可以在随后单击替代按钮时切换显示或隐藏它。 This approach can be used with multiple buttons or links so long as they all have the same class ids. 这种方法可以与多个按钮或链接一起使用,只要它们都具有相同的类ID。 For example, you may have a Show Depts button / link at top of page and another at the bottom of the page, which is the case in my current task. 例如,您可能在页面顶部有一个“显示部门”按钮/链接,而在页面底部有另一个按钮/链接,在我当前的任务中就是这种情况。

company.aspx: 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: company.aspx.cs:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM