简体   繁体   English

ASP.NET触发带有多个参数的服务器端事件

[英]ASP.NET Triggering server-side events with multiple arguments

I've got a rather lengthy question I'm afraid. 恐怕我有一个很长的问题。 I'm fairly new to ASP.NET so please bear with me. 我是ASP.NET的新手,请耐心等待。 I have built a control for an ASP.NET page that lists a number of options. 我为ASP.NET页面构建了一个控件,该控件列出了许多选项。 Each option has two clickable areas (call them buttons for the sake of simplicity). 每个选项都有两个可单击区域(为简单起见,将它们称为按钮)。 One to select the option and one to hide the option. 一种选择选项,另一种隐藏选项。


protected void Page_Load(object sender, EventArgs e)
{
  RenderOptions();
}

public void RenderOptions()
{
  for (int i = 0; i < 5; i++) {
    HtmlGenericControl div1 = new HtmlGenericControl("div");
    div1.Attributes.Add("onclick", ClientScript.GetPostBackEventReference(this, "option" + i));
    m_TreeContainer.Controls.Add(div1);

    HtmlGenericControl div2 = new HtmlGenericControl("div");
    div2.Attributes.Add("onclick", ClientScript.GetPostBackEventReference(this, "option" + i));
    m_TreeContainer.Controls.Add(div2);
  }
}

public void RaisePostBackEvent(string arg) 
{
  //do something
}

This works fine (I do implement the IPostBackEventHandler interface). 效果很好(我确实实现了IPostBackEventHandler接口)。 The problem here is that there doesn't seem to be a way for me to find which HTML element was clicked and thus which action should be performed in the RaisePostBackEvent method. 这里的问题是,似乎没有办法让我找到单击哪个HTML元素,以及因此应该在RaisePostBackEvent方法中执行哪个动作。

What I tried to do is create a new class (HtmlDivControl) which looks like this: 我试图做的是创建一个新的类(HtmlDivControl),如下所示:


class HtmlDivControl : HtmlGenericControl, IPostBackEventHandler
{
  #region Delegates
  public delegate void ClickEventHandler(object sender, string eventArgument);
  #endregion

  #region Properties
  private ClickEventHandler m_Click;
  public ClickEventHandler Click
  {
    get { return m_Click; }
    set { m_Click = value; }
  }
  #endregion

  #region Constructors
  public HtmlDivControl()
  {
  }
  #endregion

  public void RaisePostBackEvent(string eventArgument)
  {
    m_Click.Invoke(this, eventArgument);
  }
}

Now I made div1 and div2 my HtmlDivControl rather than HtmlGenericControl, set the Click property to a method (delegate) and passed the div (div1 or div2) itself as control for the GetPostBackEventReference method. 现在,我将HtmlDivControl而不是HtmlGenericControl设为div1和div2,将Click属性设置为方法(委托),并将div(div1或div2)本身作为GetPostBackEventReference方法的控件。 This time, I could not only differentiate between the divs but also pre-determine the action that should be performed. 这次,我不仅可以区分div,还可以预先确定应执行的操作。 However, the RaisePostBackEvent for controls are called after PageLoad. 但是,控件的RaisePostBackEvent在PageLoad之后调用。 So the problem I'm with now is that the whole options control is rendered before the events are handled (and thus, an option that should for instance be hidden isn't because the actual hiding happens after the rendering). 因此,我现在遇到的问题是整个选项控件是在处理事件之前呈现的(因此,例如应该隐藏的选项不是因为实际的隐藏发生在呈现之后)。 Moving the RenderOptions() call to the PageLoadComplete method doesn't help either, since then the div controls won't exist yet. 将RenderOptions()调用移至PageLoadComplete方法也无济于事,因为那时div控件尚不存在。

I'm pretty sure I'm missing something quite fundamental here. 我很确定我在这里遗漏了一些非常基本的东西。 But could someone please explain me how I should approach something like this? 但是有人可以解释一下我该如何处理这种事情吗?

ps How am I supposed to write underscores here? ps我应该在这里写下划线吗? They're used to make text italic? 它们习惯于使文本变为斜体吗? Is there some escape character? 有逃脱符吗?

For someone new to ASP.Net, you've done pretty well so far. 对于ASP.Net的新手来说,到目前为止,您已经做得不错。 Your roadblock here is actually the way you are thinking about the issue. 您在这里遇到的障碍实际上就是您思考问题的方式。 You should get a good grasp of the ASP.Net Page Lifecycle - you are missing something very fundamental. 您应该对ASP.Net页面生命周期有很好的了解-您缺少了一些非常基础的东西。

In a nutshell, you want your page to rebuild it's state to the same way it was before the postback. 简而言之,您希望页面以与回发之前相同的方式重建其状态。 Then process your events. 然后处理您的事件。 Then make any state changes. 然后进行任何状态更改。

You're thinking about it as if your html controls should know about their state change at the start of the request, which is incorrect. 您正在考虑它,好像您的html控件应该在请求开始时知道它们的状态更改一样,这是不正确的。 There has to be the rebuilding phase first. 首先必须有重建阶段。 This is critical for ASP.Net to even figure out which events to raise. 这对于ASP.Net甚至找出引发哪些事件至关重要。

What I would recommend: 我建议:

  1. move your "RenderOptions()" method to the Page_Init handler. 将您的“ RenderOptions()”方法移至Page_Init处理程序。 This will save you lots of issues if you ever incorporate ViewState into your controls. 如果您曾经将ViewState合并到控件中,这将为您节省很多问题。 (I would also rename it, as it's not truly rendering anything, it's just adding your controls to the page. Render has a specific context in ASP.Net). (我也将其重命名,因为它并没有真正呈现任何内容,只是将您的控件添加到页面中。Render在ASP.Net中具有特定的上下文)。

  2. Then, in your OnClick event handlers for your controls, simply set your controls visibility as necessary, rather than trying to control the way they are rendered. 然后,在控件的OnClick事件处理程序中,只需根据需要设置控件的可见性,而不是尝试控制控件的呈现方式。 It is always much simpler to set controls to Visible=False rather than try to change the way the controls are being rendered to the page. 它始终是更加简单的控制设置为可见=假,而不是试图改变控件被渲染到页面的方式。 Remember that if you set Visible=False, there will be zero html sent to the response for that control, but the server will still know it's on the page, so you can still deal with it. 请记住,如果将Visible = False设置为该控件的响应将发送零个html,但是服务器仍将知道它在页面上,因此您仍然可以对其进行处理。

Think about your event handlers as the place where you will change the state of the page. 将事件处理程序视为要更改页面状态的位置。 It's where your logic should be in this case, rather than in Page_Load. 在这种情况下,应该是您的逻辑所在,而不是在Page_Load中。

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

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