ASP.NET OnClick 未在具有自定义控件的 Repeater.ItemTemplate 中触发

发布于 2024-12-07 17:10:27 字数 4190 浏览 3 评论 0原文

标题有点拗口,但我对这个问题有点困惑。

我有一个搜索结果页面,其中有一个带有 Repeater 的自定义控件。转发器中的 ItemTemplate 是一个 PlaceHolder,因此我可以以特定格式构造 Item;更具体地说,我有一串以 Disease1|disease2|disease3 形式出现的“疾病”,需要为每种疾病提供链接。

现在来看一些代码:

以下是 SearchResultControl.ascx

<asp:Panel ID="SearchResultPanel" runat="server" ScrollBars="Auto">
    <asp:Repeater ID="Repeater1" runat="server" 
        onitemcreated="Repeater1_ItemCreated" 
        onitemcommand="Repeater1_ItemCommand">
        <ItemTemplate>
            <asp:PlaceHolder ID="ItemTemplatePlaceHolder" runat="server">
            </asp:PlaceHolder>
        </ItemTemplate>
        <SeparatorTemplate>
        <tr>
        <td colspan="6"><hr /></td>
        </tr>
        </SeparatorTemplate>
    </asp:Repeater>
</asp:Panel>

背后的代码:SearchResultControl.ascx.cs

protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.DataItem != null)
    {
        PlaceHolder placeHolder = e.Item.FindControl("ItemTemplatePlaceHolder") as PlaceHolder;
        Control searchResultItem = Page.LoadControl("SearchResultItem.ascx");

        DataRow row = (e.Item.DataItem as DataRowView).Row;

        if (row != null)
        {
            string diseaseState = row["DiseaseStates"] as string;
            searchResultItem.GetType().GetProperty("DiseaseStates").SetValue(searchResultItem, diseaseState, null);

            placeHolder.Controls.Add(searchResultItem);
        }
    }
}

(完全公开,我从 这个问题

SetValue调用SearchResultItem中的DiseaseStates属性它依次调用以下方法来构建链接、设置文本和事件:

private void BuildDiseaseStateLabels(string diseaseStates)
{
    PlaceHolder placeHolder = FindControl("DiseaseStatePlaceHolder") as PlaceHolder;
    string[] diseaseStateSplit = diseaseStates.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

    int count = diseaseStateSplit.Length;
    foreach (string diseaseState in diseaseStateSplit)
    {
        LinkButton diseaseStateLink = new LinkButton();
        diseaseStateLink.Text = diseaseState;
        //diseaseStateLink.Click += new EventHandler(OnDiseaseStateLinkClick);
        diseaseStateLink.CommandArgument = "<%# Eval(\"PatientID\")+ \";\" + Eval(\"PatientStatus\")+ \";\" + Eval(\"Age\")+ \";\" + Eval(\"DiseaseStates\")%>";
        diseaseStateLink.CommandName = "OnDiseaseStateLinkClick";
        //diseaseStateLink.Command += new CommandEventHandler(OnDiseaseStateLinkClick);

        placeHolder.Controls.Add(diseaseStateLink);

        if (count != 0)
        {
            Label splitLabel = new Label();
            splitLabel.Text = "|";
            placeHolder.Controls.Add(splitLabel);
        }
    }
}

这是 SearchResultItem 的布局

<div id="SearchResultItemDiv" class="MainSearchResultItem">
    <asp:PlaceHolder ID="DiseaseStatePlaceHolder" runat="server">
    </asp:PlaceHolder>
</div>

最初我尝试设置 Click 事件,但是那根本不起作用。然后,我设置了 CommandArgument 和 CommandName,但这似乎没有解决问题。我认为可能需要设置 Command 事件,但同样,没有运气。我应该注意,当单击链接时,将调用 SearchResultControl.ascx.cs 中的 Repeater1_ItemCreated 。但由于 e.Item.DataItem 中没有数据,所以我丢失了结果。

在关于相同问题的问题之一问题,建议添加 OnItemCommand,但即使这样也不会被调用。

我还阅读了 A Stumper of an ASP.NET Question一个 ASP.NET 问题的难题:已解决!,但无济于事。

我可能做错了什么?所有正确的事件连接似乎都在那里,我正在检查 IsPostBack 并且不再执行 DataBind()blaaargharaggh

帮助总是非常感激。

Title is a bit of a mouthful, but I'm a bit stuck on this issue.

I have a search result page with has a custom control that has a Repeater. The ItemTemplate in the repeater is a PlaceHolder so I can construct the Item in a particular format; more specifically, I have a string of 'diseases' that come in the form of Disease1|disease2|disease3 and need to be given links for each disease.

Now for some code:

The following is the SearchResultControl.ascx

<asp:Panel ID="SearchResultPanel" runat="server" ScrollBars="Auto">
    <asp:Repeater ID="Repeater1" runat="server" 
        onitemcreated="Repeater1_ItemCreated" 
        onitemcommand="Repeater1_ItemCommand">
        <ItemTemplate>
            <asp:PlaceHolder ID="ItemTemplatePlaceHolder" runat="server">
            </asp:PlaceHolder>
        </ItemTemplate>
        <SeparatorTemplate>
        <tr>
        <td colspan="6"><hr /></td>
        </tr>
        </SeparatorTemplate>
    </asp:Repeater>
</asp:Panel>

The code behind: SearchResultControl.ascx.cs

protected void Repeater1_ItemCreated(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.DataItem != null)
    {
        PlaceHolder placeHolder = e.Item.FindControl("ItemTemplatePlaceHolder") as PlaceHolder;
        Control searchResultItem = Page.LoadControl("SearchResultItem.ascx");

        DataRow row = (e.Item.DataItem as DataRowView).Row;

        if (row != null)
        {
            string diseaseState = row["DiseaseStates"] as string;
            searchResultItem.GetType().GetProperty("DiseaseStates").SetValue(searchResultItem, diseaseState, null);

            placeHolder.Controls.Add(searchResultItem);
        }
    }
}

(Full disclosure, I got this idea from this question)

The SetValue calls the DiseaseStates property in SearchResultItem which in turn calls the following method to build the links, set the text, and the events:

private void BuildDiseaseStateLabels(string diseaseStates)
{
    PlaceHolder placeHolder = FindControl("DiseaseStatePlaceHolder") as PlaceHolder;
    string[] diseaseStateSplit = diseaseStates.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);

    int count = diseaseStateSplit.Length;
    foreach (string diseaseState in diseaseStateSplit)
    {
        LinkButton diseaseStateLink = new LinkButton();
        diseaseStateLink.Text = diseaseState;
        //diseaseStateLink.Click += new EventHandler(OnDiseaseStateLinkClick);
        diseaseStateLink.CommandArgument = "<%# Eval(\"PatientID\")+ \";\" + Eval(\"PatientStatus\")+ \";\" + Eval(\"Age\")+ \";\" + Eval(\"DiseaseStates\")%>";
        diseaseStateLink.CommandName = "OnDiseaseStateLinkClick";
        //diseaseStateLink.Command += new CommandEventHandler(OnDiseaseStateLinkClick);

        placeHolder.Controls.Add(diseaseStateLink);

        if (count != 0)
        {
            Label splitLabel = new Label();
            splitLabel.Text = "|";
            placeHolder.Controls.Add(splitLabel);
        }
    }
}

This is the layout for the SearchResultItem

<div id="SearchResultItemDiv" class="MainSearchResultItem">
    <asp:PlaceHolder ID="DiseaseStatePlaceHolder" runat="server">
    </asp:PlaceHolder>
</div>

Initially I tried setting the Click event, but that doesn't work at all. I then set the CommandArgument and CommandName but that didn't seem to do the trick. I figured the Command event might need to be set, but again, no luck. I should note that when a link is clicked the Repeater1_ItemCreated in SearchResultControl.ascx.cs is called. But since there is no data in e.Item.DataItem is null and I lose the results.

In one of the questions regarding the same issue, it was suggested that the OnItemCommand be added, but even that doesn't get called.

I also read A Stumper of an ASP.NET Question and A Stumper of an ASP.NET Question: SOLVED!, to no avail.

What could I possibly be doing wrong? All of the correct event hookups seem there, I'm checking for IsPostBack and not doing DataBind() again. blaaargharaggh

Help is always greatly appreciate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戴着白色围巾的女孩 2024-12-14 17:10:27

我相信您遇到此问题是因为 LinkBut​​ton 控件在页面生命周期中重新创建得太晚了。您必须记住,当页面回发时,该控件在技术上不再存在,因此无法触发事件处理程序。

如果您可以在到达 Page_Load 事件之前的某个位置重新创建 LinkBut​​ton 控件(例如 OnInit),那么一切都应该正常工作。

对于简单页面,上述方法通常效果很好,但在某些情况下,在 OnInit 期间重新创建控件需要大量开销,例如在 ViewState 中存储计数器或数组,以便您可以跟踪需要的控件回发后重新创建。在这些情况下,我建议查看 Denis Bauer 的DynamicControlsPlaceHolder。该控件能够持久保存动态控件,而不需要任何额外的代码,这非常棒。

这是最新版本的链接:
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx

I believe you're running into this issue because the LinkButton controls are recreated too late in the page lifecycle. You have to remember that when the page is posted back, the control technically does not exist anymore, so the event handler cannot be fired.

If you can recreate the LinkButton controls somewhere before the Page_Load event is reached, like OnInit for example, everything should work fine.

For simple pages the above usually works very well, but there are circumstances where recreating controls during OnInit requires a lot of overhead, such as storing counters or arrays in ViewState so you can keep track of the controls that need to be recreated after postback. In these situations I would suggest taking a look at the DynamicControlsPlaceHolder by Denis Bauer. This control is capable of persisting dynamic controls without any addtional code required, which is pretty awesome.

Here's a link to the latest version:
http://www.denisbauer.com/ASPNETControls/DynamicControlsPlaceholder.aspx

春夜浅 2024-12-14 17:10:27

问题可能是您没有再次执行 DataBind()

因为您正在动态构建按钮,所以当页面回发时,按钮尚未创建,并且无法确定应触发哪个单击事件。

尝试去掉 IsPostBack 检查,以便每次加载页面时,您都需要重新构建 repeater

The problem might be that you're not doing the DataBind() again.

Because you're building the buttons on the fly, when the page post backs, the buttons haven't been created and are unable to work out which click event it should be firing.

Try getting rid of the IsPostBack check, so each time the page loads, you're re-build the repeater.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文