在jquery选项卡下按需加载usercontrols

时间:2011-11-17 07:13:29

标签: c# asp.net jquery user-controls asp.net-ajax

我在usercontrol上有几个jquery选项卡,在每个选项卡下加载一个单独的用户控件。每个用户控件都是唯一的。一切正常,但整体页面响应太慢。为了提高性能,我尝试按需在这些选项卡下加载少量用户控件(即单击选项卡)。可能没有回帖...... ajaxish。 谁能指导我? 我也尝试过this教程和this,但没有取得任何成功。我已附加父usercontrol的代码。

<ul id="tabs">
<li class="active">Rewards</li>
<li id="liCoupons">Coupons</li>
<li id="liLibrary">Library</li>
<li id="liProducts">Favorite</li>
<li id="liPreferences">Preferences</li></ul><ul id="tabPanes" class="rewardsTabs">
<li>
    <div class="wrapper active">
        <uc:Rewards ID="wellness" runat="server" />

    </div>
</li>
<li id="liCoupons">
    <div class="wrapper">
        <uc:Coupon runat="server" />
    </div>
</li><li id="liLibrary">
    <div class="wrapper">
        <uc:Library runat="server" />
    </div>
</li><li id="liProducts">
    <div class="wrapper">
        <uc:Products runat="server" />
    </div>
</li>
<li>
    <div class="wrapper">
        <div class="preferences">
            <uc:Preferences runat="server"/>
        </div>

    </div>
</li>

9 个答案:

答案 0 :(得分:12)

你提到的second link应该有效。您无需在标记中定义任何用户控件。

<ul id="tabs">
    <li class="active">Rewards</li>
    <li id="liCoupons">Coupons</li>
    <li id="liLibrary">Library</li>
    <li id="liProducts">Favorite</li>
    <li id="liPreferences">Preferences</li>
</ul>
<div id="results" class="wrapper"></div>

每个标签点击都会进行ajax调用

$.ajax({
       type: "POST",
       url: "Default.aspx/WebMetodToCall", 
       data: data, // I wouldn't prefer passing webmethod name here
       contentType: "application/json; charset=utf-8",
       dataType: "json",
       success: function (msg) {
           $('#result').html(msg.d);
       },
       failure: function (msg) 
           //error
       }
   });

到网络方法。

[WebMethod]
   public static string Rewards()
   {
       return RenderControl("~/controls/rewardsControl.ascx");
   }

[WebMethod]
   public static string Coupons()
   {
       return RenderControl("~/controls/couponsControl.ascx");
   }    
...

每个方法仅呈现请求的控件。同样在您的方法中,您可以根据需要保留或提取视图状态。渲染后,webmethod应该传回html字符串以注入占位符。

如果你试过这个并且一次成功渲染一个控件但仍然看到缓慢,那么在获取数据时你会遇到一些后端问题。如果您的控件数据量很大,我建议您进行一些服务器端缓存。

希望这有帮助。

答案 1 :(得分:6)

您的用户控件是否依赖回发和视图状态才能正常工作?使用AJAX获取要在选项卡中显示的用户控件HTML相对容易,但是然后在该控件上回发将整个数据发送到实际页面(可能没有加载用户控件)。所以基本大纲是

  1. 使用隐藏变量或视图状态跟踪活动选项卡。
  2. 在早期页面循环中基于活动选项卡加载用户控件。最好的选择是初始阶段(不是视图状态在这里不可用,所以你必须在隐藏变量中存储活动选项卡并通过Request.Forms集合访问它。)
  3. 为每个用户控件提供一个ID,它应与tab到tab不同。 ID对于加载视图状态非常重要。
  4. 如果在切换选项卡时出现视图状态错误,那么您需要首先加载上一个选项卡的用户控件,然后再加载到页面的后一页(比如加载/预渲染),卸载它并为活动选项卡加载新的用户控件
  5. 您可以在每个选项卡窗格中使用占位符或面板控件将用户控件加载到正确的位置。
  6. 毋庸置疑,在更改jquery选项卡时,您需要使用post-back脚本提交表单。每次回发后,您都需要有一个脚本来重新初始化选项卡并选择活动选项卡。
  7. 为了获得更好的用户体验,请将整个内容放入UpdatePanel。

答案 2 :(得分:5)

也许使用指向下面定义的服务的锚点。例如,

<li><a href="...webservices/ControlServce.svc/Content?cType=Rewards" class="wrapper active"></a></li> 

/// <summary>
/// Service used by ajax for loading social media content
/// </summary>
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ControlService
{
    /// <summary>
    /// Streams html content
    /// </summary>
    /// <param name="type">type of control</param>
    /// <returns>html stream of content</returns>
    [OperationContract]
    [WebGet(UriTemplate = "Content?cType={cType}")]
    public Stream GetContent(string cType)
    {
        var tw = new StringWriter();
        var writer = new Html32TextWriter(tw);

        var page = new Page();
        var control = page.LoadControl(cType);

        control.RenderControl(writer);

        writer.Close();

        var stream = new MemoryStream(Encoding.UTF8.GetBytes(tw.ToString()));

        WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
        WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "no-cache");
        return stream;
    }
}

答案 3 :(得分:5)

您需要进行Ajax调用才能实现此目的。 现在您可以选择调用AJAX:

1 - 通过SOAP Web服务调用(每个Web方法都需要ASP AjaxScriptManager引用)。

2-通过WCF服务呼叫作为上一个答案。

3 - 通过休息服务呼叫。

4-通过Jquery ajax方法调用,但请求必须转到外部页面,如“Actions.aspx”,因此当您调用方法时,HTTPRequest将进入Actions页面,然后它将在其响应中返回返回的数据。 $.Ajax(url,data,action,successMethod); // this is the fastest way I tried them all.

这是你应该做的: 1-在更改选项卡事件上,使用上述选项中的相应Ajax调用方法调用您的方法。

成功方法中的

2-使用返回的数据,但最好使用eval(data)作为DataTime对象。

这里有一些例子解释了如何进行这个调用:

var helper = {
callAjax: function(sentData, successFun) {
        jQuery.ajax({
            url: "/Actions.aspx",
            type: "Get",
            data: sentData,
            cache: true,
            dataType: "json",
            success: successFun
        });
    }
};

helper.callAjax('request=getCities&countryID=' + countryID, function (args) {
   var result = eval(args); // this object will contain the returned data
var htmlData = '';
    for (var i=0;i<result.length;i++){
    // write your HTML code by jQuery like this
    htmlData  += '<div>' +  result[i].title + '</div>';
}
$('#tab3').html(htmlData);
});

现在在Actions.ASPX代码中使用以下内容:

 protected void Page_Load(object sender, EventArgs e)
    {
        object _return = new
        {
            error = "",
            status = true
        };
        JavaScriptSerializer _serializer = new JavaScriptSerializer();
        if (!Page.IsPostBack)
        {
            string str = Request.QueryString["request"].ToString();
            switch (str.ToLower())
            {
case "getcities":
                    int countryID = Convert.ToInt32(Request.QueryString["countryID"].ToString());
                    _return = JQueryJson.Core.City.getAllCitiesByCountry(countryID).Select(_city => new
                    {
                        id = _city.ID,
                        title = _city.Name
                    });
                    _serializer = new JavaScriptSerializer();
                    Response.ClearContent();
                    Response.ClearHeaders();
                    Response.ContentType = "text/json";
                    Response.Write(_serializer.Serialize(_return));
                    break;
}
// etc........
}

答案 4 :(得分:3)

如果用jquery稍微调整一下,这应该有效:
http://blogs.msdn.com/b/sburke/archive/2007/06/13/how-to-make-tab-control-panels-load-on-demand.aspx

或者你只是使用asp.net标签。

答案 5 :(得分:3)

你应该使用jquery和webmethod来寻找第二个链接。这样,您实际上可以根据需要填充选项卡,而不会使页面变得很重。

答案 6 :(得分:3)

在我看来,解决问题的最快方法(但不一定是最好的长期解决方案)是将所有UserControl包装在.aspx页面中。在这种情况下,您只需将父UserControl标记移动到新的.aspx页面,然后通过AJAX调用它。

假设您将此页面称为 Menu.aspx ,并进一步假设您不需要传递到此页面的任何数据(也就是说,它可以跟踪它自己的所有内容)数据内部),你的jQuery AJAX调用看起来像这样:

function GetMenu ($placeholder) {
    $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", dataType: "json",
        url: "Menu.aspx",
        done: function (result) {
            $placeholder.html(result.d);
        },
        fail: function () {
            $placeholder.html("Error loading menu.");
        }
    });
}

一些注意事项:

  1. donefail将取代jQuery 1.8中的successerror,因此您使用的任何jQuery AJAX都应该计划此转换。
  2. 我把它包装在一个函数中很大程度上是因为我更喜欢将AJAX调用放在JS类和函数中,然后引用这些对象。使用菜单,你不可能有几个不同的页面通过AJAX加载相同的数据(因为这将出现在某种母版页上,我猜测),但是它“#”;总是善于养成做这些事情的习惯。
  3. 根据您对紧密耦合的HTML / JavaScript的看法,您可以使用回调函数替换上面的$placeholder。从您的菜单所在的页面调用它将类似于:

    $(document).ready(function () {
        GetMenu(MenuCallback);
    });
    
    function MenuCallback(menuHtml) {
        $("#menu").html(menuHtml); // I'm assuming the ID of your ul/span/div tag here.
    }
    
  4. 有些人(包括我自己)使用$前缀来区分JavaScript和jQuery变量。所以在这里,$placeholder是一个jQuery变量。

  5. 您可以将此$.ajax来电重新编写为type: "GET",这会更有效率,但我不确定UserControl是否有效在这方面会引起问题。通常情况下,如果我通过AJAX加载整个.aspx页面,我会使用GET而不是POST。您不必进行太多改动即可尝试:只需关闭type媒体资源,然后将result.d更改为result

答案 7 :(得分:3)

我认为最好的解决方案是实现客户回调

http://msdn.microsoft.com/en-us/library/ms178210.aspx

当用户点击某个标签时,onclick事件会调用名称为tab作为参数的js func,而该标签会调用具有相同参数的服务器代码。

在代码中,您可以根据单击的选项卡加载所需的控件。 现在你需要将控件渲染为html并将tham发送回js函数。 现在你在js函数中有控件,找到你要插入代码的位置。

这应该在理论上有效并且不复杂:))

答案 8 :(得分:0)

asnwer(不是我的)对这个问题可能对你有用:

Asynchronous loading of user controls in a page

它表示在使用用户控件上的表单回发时存在问题,但是可以使用带有ajax帖子的独立表单。你必须考虑在页面上发布表单时会发生什么,但不应该是不可克服的。不应该是你不能把它变成你提到的ashx处理程序。