ASP.NET 使用多个参数触发服务器端事件
恐怕我有一个相当长的问题。 我对 ASP.NET 还很陌生,所以请耐心等待。 我为 ASP.NET 页面构建了一个控件,其中列出了许多选项。 每个选项都有两个可点击区域(为了简单起见,将它们称为按钮)。 一种用于选择选项,另一种用于隐藏选项。
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
}
这工作正常(我确实实现了 IPostBackEventHandler 接口)。 这里的问题是,我似乎没有办法找到单击了哪个 HTML 元素,从而确定应该在 RaisePostBackEvent 方法中执行哪个操作。
我尝试做的是创建一个新类(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);
}
}
现在我将 div1 和 div2 设置为我的 HtmlDivControl 而不是 HtmlGenericControl,将 Click 属性设置为方法(委托)并传递 div(div1 或 div2)本身作为 GetPostBackEventReference 方法的控件。 这次,我不仅可以区分 div,还可以预先确定应该执行的操作。 但是,控件的 RaisePostBackEvent 在 PageLoad 之后调用。 所以我现在遇到的问题是整个选项控件在处理事件之前渲染(因此,应该隐藏的选项并不是因为实际隐藏发生在渲染之后)。 将 RenderOptions() 调用移至 PageLoadComplete 方法也无济于事,因为那时 div 控件还不存在。
我很确定我在这里遗漏了一些非常基本的东西。 但有人可以解释一下我应该如何处理这样的事情吗?
附注 我应该如何在这里写下划线? 它们用于使文本变为斜体? 有没有转义字符?
I've got a rather lengthy question I'm afraid. I'm fairly new to ASP.NET so please bear with me.
I have built a control for an ASP.NET page that lists a number of options. 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). 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.
What I tried to do is create a new class (HtmlDivControl) which looks like this:
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. This time, I could not only differentiate between the divs but also pre-determine the action that should be performed. However, the RaisePostBackEvent for controls are called after 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.
I'm pretty sure I'm missing something quite fundamental here. But could someone please explain me how I should approach something like this?
p.s.
How am I supposed to write underscores here? They're used to make text italic? Is there some escape character?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于刚接触 ASP.Net 的人来说,到目前为止您已经做得很好了。 这里的障碍实际上是你思考问题的方式。 您应该很好地掌握 ASP.Net 页面生命周期 - 您错过了一些非常基本的东西。
简而言之,您希望页面将其状态重建为回发之前的状态。 然后处理您的事件。 然后进行任何状态更改。
你认为你的 html 控件应该在请求开始时知道它们的状态变化,这是不正确的。 首先必须有重建阶段。 这对于 ASP.Net 确定要引发哪些事件至关重要。
我的建议是:
将“RenderOptions()”方法移至 Page_Init 处理程序。 如果您将 ViewState 合并到控件中,这将为您节省很多问题。 (我还会重命名它,因为它并没有真正渲染任何内容,它只是将控件添加到页面。渲染在 ASP.Net 中具有特定的上下文)。
然后,在控件的 OnClick 事件处理程序中,只需根据需要设置控件的可见性,而不是尝试控制它们的呈现方式。 将控件设置为 Visible=False 总是比尝试更改控件呈现到页面的方式简单得多。 请记住,如果您设置 Visible=False,将有零个 html 发送到该控件的响应,但服务器仍然知道它在页面上,因此您仍然可以处理它。
将事件处理程序视为更改页面状态的地方。 在这种情况下,您的逻辑应该位于此位置,而不是位于 Page_Load 中。
For someone new to ASP.Net, you've done pretty well so far. 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.
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. There has to be the rebuilding phase first. This is critical for ASP.Net to even figure out which events to raise.
What I would recommend:
move your "RenderOptions()" method to the Page_Init handler. This will save you lots of issues if you ever incorporate ViewState into your controls. (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).
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. 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.
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.