【问题标题】:C# dynamically created user control button click not workingC#动态创建的用户控件按钮单击不起作用
【发布时间】:2018-04-22 20:03:46
【问题描述】:

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

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

我已经阅读了解决此问题的一种方法是在 Page_Init 中创建动态用户控件,但我是通过单击主页按钮创建用户控件。另外,我没有像往常一样在主页后面的代码中声明用户控件,但确实有一个占位符,其中添加了用户控件。

我还读到,您可以在主页上添加一个委托以供单击用户控制按钮,但该示例似乎有很多必要的代码来完成这样一个简单的事情,我认为必须有更好的方法。

这里是相关代码sn-ps:

公司.aspx:

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

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

公司.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
    }

【问题讨论】:

    标签: c# dynamic webforms user-controls placeholder


    【解决方案1】:

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

    但是,添加的控件无法赶上回发数据处理。要使添加的控件参与回发数据处理(包括验证),必须将控件添加到 Init 事件而不是 Load 事件中。

    您将在click 事件中添加控件,该事件发生在initload 事件之后,因此回发将不起作用。

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

    【讨论】:

    • Racil Hilan:我在主页上添加了一个 OnInit 来检查 EVENTTARGET,如果 ID 是主页按钮的 ID,那么我调用 CreateDeptsUserControl 方法。这行得通,该方法创建了用户控件。但是我有同样的问题,单击用户控件按钮不会触发该按钮事件,而只是重新加载主页。但我认为我们走在正确的轨道上。在 OnInit 中,我认为我需要以某种方式连接用户控件按钮事件?
    【解决方案2】:

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

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

    在用户控件 OnInit 事件中,我有几个保护条件,用于检查导致页面/用户控件加载的 EVENTTARGET(如果有)。如果 EVENTTARGET(控件 ID)是主页按钮的 ID,则执行将继续并调用 LoadSomeData() 并设置用户控件 Visible = true。否则,如果任一保护条件评估为 false,我们将退出并且不会加载用户控件,因此不会浪费 db / service 调用。

    公司.aspx:

        <asp:Button id="btnShowDeptsUserControl" runat="server" OnClick="btnShowDeptsUserControl_Click">Show Depts</asp:Button>
    
        <uc1:ucDepartments ID="ucDepartments" runat="server" Visible="False" />
    

    公司.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 设置为可以在主页文档上检查的值,准备执行一些 jquery 内容,例如将用户控件滚动到视图中(如果它很远)在页面下方(我在当前任务中实际上正在执行此操作)。

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

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

    公司.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>
    

    公司.aspx.cs:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 2012-09-17
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      相关资源
      最近更新 更多