一个用户控件在 AJAX 回发期间更新另一个用户控件?

发布于 2024-07-17 09:12:05 字数 977 浏览 7 评论 0原文

我开发了一个显示产品列表的用户控件,效果非常好。 然后我将此用户控件放入另一个用户控件中,该控件允许用户选择不同的标准和产品 UC 更新以显示这些产品,所有这些都非常流畅,并且通过 UpdatePanel 使用 AJAX。

一切都工作得很好......然后另一个要求出现了。“搜索”控件需要与产品控件分开(以便它们可以单独定位)。 最初,我认为这没有问题,因为我会给搜索控件提供对产品控件的引用,然后它会通过引用与其对话,而不是直接在控件内部(已被删除)。

他们确实会说话。 但产品控件加载,但拒绝显示。

我查了一下,它是通过参考传递的,而不是副本(据我所知)。

搜索控件中有一个更新面板。 产品控件中有一个更新面板。 然后,为了更好地衡量,在实际的搜索 aspx 页面中,它们周围有一个更新面板。

我尝试将产品控制更新面板设置为有条件,然后手动触发 .Update() 方法。

这里有什么秘密?

蒂亚!

已解决

感谢Jamie Ide提供使用事件的提示。

搜索控件和产品控件仍然具有内部更新面板,并且此特定页面上不再有它们。

搜索控件现在引发 OnSearchResultsUpdated 事件并公开属性中找到的项目。 该页面订阅此事件并获取属性并将它们传递给产品控件,并触发产品控件上的 .Refresh() 方法,该方法只需调用其内部 updatepanel 上的 .Update() 方法。

产品控制(仅供参考)接受多种不同口味的产品。 不同 SKU 的列表、产品 ID 列表、数据库中的命名集合以及最终的给定产品类别。

我们的设计师需要能够创建一个新页面,将控件放在上面并设置一些属性,瞧! 新网站页面。 他们不想需要程序员的参与。 因此,保持控件独立是一项要求。 幸运的是,我所做的所有更改仍然完全适用于产品控件的其他用途。

再次非常感谢!

I developed a user control that displays a list of products and it works pretty good. Then I dropped this user control into another user control that allows the user to pick different criteria and the product UC updates to show those products, all pretty slick and with AJAX via UpdatePanel.

All was working just fine... then another requirement came in. The "search" control needs to be separate from the product control (so they can be positioned separately). Initially, I thought this was no problem as I would give the search control a reference to the product control and then it would talk to it via reference instead of directly inside the control (which has been removed).

And they do talk. But the product control loads, but refuses to display.

I checked and it is being passed via reference and not a copy ( as best I can tell ).

There is an updatepanel in the search control. There is an update panel in the product control. And then for good measure, there is an update panel surrounding them both in the actual search aspx page.

I've tried setting the product control update panel to conditional and then fire the .Update() method manually.

What's the secret here?

TIA!

SOLVED

Thanks to Jamie Ide for the tip to use events.

Search Control and Product control still have internal update panels, and NO LONGER have them on this particular page.

Search Control now raises an event OnSearchResultsUpdated and exposes the found items in properties. The page subscribes to this event and takes the properties and passes them to the product control and triggers triggers a .Refresh() method on the product control which simply calls the .Update() on its internal updatepanel.

The Product control, FYI, accepts products in several different flavors. A list of distinct SKUs, a list of product ids, a named collection in our database and finally a given product category.

Our designers need to be able to create a new page, drop the control onto it and set some properties and voila! New site page. They don't want to require a programmer's involvement. So keeping the controls self contained is a requirement. Fortunately all the changes I made still work completely with the other uses of the product control.

THANKS AGAIN SO MUCH!

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

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

发布评论

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

评论(4

去了角落 2024-07-24 09:12:05

我认为这里没有足够的信息可供使用,但我最好的猜测是产品控件没有绑定数据。 您可以尝试从搜索控件(或 Product 控件中导致 DataBind() 的内容调用 myProdcutsCtrl.DataBind(),例如 myProductCtrl.Search(value1, value2, value3)。

您可以尝试的另一件事是删除 UpdatePanels 和看看事情是否有效。然后在核心功能运行后将它们添加回来

更新:我已经在此处放置了一些示例代码,我相信它可以实现您想要的功能。为了节省空间,但包括使其运行所需的所有代码,希望这至少能给您一些参考:

EnablePartialRendering

  1. =“true | false”将其设置为 false 将强制自然回发和有助于调试 UpdatePanel 问题。
  2. 确保您在屏幕上看到 Loading... (可能太快,具体取决于您的开发计算机)

Page.aspx

<%@ Register Src="~/Product.ascx" TagPrefix="uc" TagName="Product" %>
<%@ Register Src="~/Search.ascx" TagPrefix="uc" TagName="Search" %>

。 ..

<asp:ScriptManager runat="server" ID="sm" EnablePartialRendering="true" />
Loaded <asp:Label ID="Label1" runat="server"><%= DateTime.Now %></asp:Label>

<asp:UpdateProgress runat="server" ID="progress" DynamicLayout="true">
<ProgressTemplate><b>Loading...</b></ProgressTemplate>
</asp:UpdateProgress>

<uc:Search runat="server" ID="search" ProdcutControlId="product" />
<uc:Product runat="server" ID="product" />

Search.ascx

<asp:UpdatePanel runat="server" ID="searchUpdate" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<p>
    <asp:Label runat="server" AssociatedControlID="filter">Less than</asp:Label>
    <asp:TextBox runat="server" ID="filter" MaxLength="3" />
    <asp:Button runat="server" ID="search" Text="Search" OnClick="SearchClick" />
</p>
</ContentTemplate>
</asp:UpdatePanel>

Search.ascx.cs

    public string ProdcutControlId { get; set; }
    protected void SearchClick(object sender, EventArgs e)
    {
        Product c = this.NamingContainer.FindControl(ProdcutControlId) as Product;
        if (c != null)
        {
            c.Search(filter.Text);
        }

    }

Product.ascx

<asp:UpdatePanel runat="server" ID="productUpdate" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<asp:Label runat="server">Request at <%= DateTime.Now %></asp:Label>
<asp:ListView runat="server" ID="product">
<LayoutTemplate>
    <ul>
        <li id="itemPlaceHolder" runat="server" />
    </ul></LayoutTemplate>
<ItemTemplate>
    <li><%# Container.DataItem %></li></ItemTemplate>
</asp:ListView>

</ContentTemplate>
</asp:UpdatePanel>

Product.ascx.cs

IEnumerable<int> values = Enumerable.Range(0, 25);
public void Search(string val)
{
    int limit;
    if (int.TryParse(val, out limit))
        product.DataSource = values.Where(i => i < limit);
    else
        product.DataSource = values;
    product.DataBind();
    productUpdate.Update();
}

代码并不代表最佳实践,只是一个简单的例子!

I don't think there's really enough information to work with here, but my best guess is that the Product control is not getting data bound. You may try calling myProdcutsCtrl.DataBind() from the search control (or something inside the Product control that cause a DataBind() for instance myProductCtrl.Search(value1, value2, value3).

One other thing you might try is removing the UpdatePanels and seeing if things work. Then add them back in once you get core functionality going.

UPDATE: I've gone ahead and put some example code that works here which I believe accomplishes what you want. What follows are snippets for the sake of saving space, but include all code necessary to make it run. Hopefully this will at least give you something for reference.

Things to try:

  1. EnablePartialRendering="true|false" setting it to false will force the natural postbacks and is good for debugging UpdatePanel problems.
  2. Make sure you are seeing Loading... come up on your screen. (maybe too fast depending on your dev computer)

Page.aspx

<%@ Register Src="~/Product.ascx" TagPrefix="uc" TagName="Product" %>
<%@ Register Src="~/Search.ascx" TagPrefix="uc" TagName="Search" %>

...

<asp:ScriptManager runat="server" ID="sm" EnablePartialRendering="true" />
Loaded <asp:Label ID="Label1" runat="server"><%= DateTime.Now %></asp:Label>

<asp:UpdateProgress runat="server" ID="progress" DynamicLayout="true">
<ProgressTemplate><b>Loading...</b></ProgressTemplate>
</asp:UpdateProgress>

<uc:Search runat="server" ID="search" ProdcutControlId="product" />
<uc:Product runat="server" ID="product" />

Search.ascx

<asp:UpdatePanel runat="server" ID="searchUpdate" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<p>
    <asp:Label runat="server" AssociatedControlID="filter">Less than</asp:Label>
    <asp:TextBox runat="server" ID="filter" MaxLength="3" />
    <asp:Button runat="server" ID="search" Text="Search" OnClick="SearchClick" />
</p>
</ContentTemplate>
</asp:UpdatePanel>

Search.ascx.cs

    public string ProdcutControlId { get; set; }
    protected void SearchClick(object sender, EventArgs e)
    {
        Product c = this.NamingContainer.FindControl(ProdcutControlId) as Product;
        if (c != null)
        {
            c.Search(filter.Text);
        }

    }

Product.ascx

<asp:UpdatePanel runat="server" ID="productUpdate" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<asp:Label runat="server">Request at <%= DateTime.Now %></asp:Label>
<asp:ListView runat="server" ID="product">
<LayoutTemplate>
    <ul>
        <li id="itemPlaceHolder" runat="server" />
    </ul></LayoutTemplate>
<ItemTemplate>
    <li><%# Container.DataItem %></li></ItemTemplate>
</asp:ListView>

</ContentTemplate>
</asp:UpdatePanel>

Product.ascx.cs

IEnumerable<int> values = Enumerable.Range(0, 25);
public void Search(string val)
{
    int limit;
    if (int.TryParse(val, out limit))
        product.DataSource = values.Where(i => i < limit);
    else
        product.DataSource = values;
    product.DataBind();
    productUpdate.Update();
}

Code does NOT represent best practices, just a simple example!

江城子 2024-07-24 09:12:05

我对 AJAX 相当陌生,但我认为用户控件拥有 UpdatePanel 不是一个好主意。 我还建议您不要让用户控件相互引用; 他们应该通过其容器控制的事件和方法进行通信。

我对两个用户控件执行类似的操作以显示主详细信息。 当从列表中选择一个项目时,主控将引发一个事件,包含的页面处理该事件并调用详细信息显示上的方法来显示所选项目。 如果我没记错的话,我的第一次尝试在用户控件中使用了 UpdatePanel,但我无法使其工作。 将用户控件放在页面上的 UpdatePanel 内效果很好。

I'm fairly new to AJAX, but I don't think it's a good idea for user controls to have UpdatePanels. I would also advise you not to have the user controls reference each other; they should communicate through events and methods controlled by their container.

I do something similar with two user controls for a master-details display. The master raises an event when an item is selected from a list, the containing page handles the event and calls a method on the details display to display the selected item. If I remember correctly, my first attempt had UpdatePanels in the user controls and I wasn't able to make that work. Having the user controls inside an UpdatePanel on the page works fine.

猫九 2024-07-24 09:12:05

如果我理解正确,您的布局如下:

Outer UpdatePanel
  SearchControl
    Search UpdatePanel
  ProductControl
    Product UpdatePanel
      Databound Control

实际上正在调用哪一个更新面板?

我假设如果您使用 FiddlerFirebug 如果您使用的是 Firefox,您没有看到产品更新面板的任何 HTML 回来吗?

您是否尝试过做类似的事情:

UpdatePanel productUpdate = 
              Page.FindControl("Product UpdatePanel") as UpdatePanel;

if (null != productUpdate){
  productUpdate.Update();
}

If I understand you right you have a layout like this:

Outer UpdatePanel
  SearchControl
    Search UpdatePanel
  ProductControl
    Product UpdatePanel
      Databound Control

Which one of those update panels is actually being called?

I assume that if you check the network traffic with something like Fiddler or Firebug if you're using Firefox, you aren't seeing any HTML for the product update panel coming back?

Have you tried doing something like:

UpdatePanel productUpdate = 
              Page.FindControl("Product UpdatePanel") as UpdatePanel;

if (null != productUpdate){
  productUpdate.Update();
}
白况 2024-07-24 09:12:05

默认情况下,如果从 UpdatePanel 进行回发,则只有该控件将被更新/重新呈现(这称为部分页面呈现)。

要同时更新/重新呈现其他 UpdatePanel,您必须:

  • 将其 UpdateMode 属性设置为 始终
  • 添加使回发到其触发器集合的控件

检查 MSDN 中的此页面了解详细信息。

By default, if a postback is made from an UpdatePanel, only that control will be updated/re-rendered (this is called partial page-rendering).

To also update/re-render other UpdatePanels, you have to either:

  • set their UpdateMode property to Always
  • add the control that makes the postback to their Triggers collection

Check this page in MSDN for details.

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