-2

好的,所以我有一个问题。我目前正在开发一个使用 ASP.NET AJAX 的 Telerik 框架的项目,尽管这并不重要,因为我在这部分工作中完全(几乎)绕过了 Telerik。

我正在将一个类似于 facebook 的聊天程序整合到我们公司的 CRM 系统中,虽然到目前为止一切顺利,但我遇到了障碍。问题是当我尝试“创建一个新的聊天框”时。我将 asp 控件 UpdatePanel 与 jQuery $.ajax 调用结合使用,将 JSON 方法名称传递给我的代码隐藏文件。这是 JSON 逻辑:

双击用户列表中的用户:

$telerik.$(".UserListEntry").dblclick(function () {
                var ToName = $telerik.$(this).children(".UserListEntryName").text();
                var FromName = $telerik.$("#lkUserGeneralSettings").text();
                $telerik.$.ajax({
                    type: 'POST',
                    url: 'DefaultHandler.ashx',
                    data: { "ToName": ToName, "FromName": FromName },
                    success: CreateChatBox(),
                    error: function (response) { alert("error: 001"); }
                });
            });

CreateChatBox 回调:

function CreateChatBox() {
            $telerik.$.ajax({
                type: 'POST',
                url: 'Default.aspx',
                data: { MethodName: "CreateChatBox" },
                success: ForceAsyncPostback,
                error: function (response) { alert("error: 002"); }
            });
        }

强制 asyncpostback (不应该,但这甚至不起作用!):

function ForceAsyncPostback() {
            var UpdatePanel1 = '<%=Panel3.ClientID%>';

            if (UpdatePanel1 != null) {
                __doPostBack(UpdatePanel1, '');
            }
            alert("Success");
        }

UpdatePanel 是通过各种文字和一些硬编码的 html good-ole' 风格的 div 创建的。问题在于所述元素的动态创建,这很好用。事实上,如果我将其放入 PageLoad 事件中,我的代码(我将在下面发布)创建并显示一切都非常好。

无论如何,这是.aspx:

<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:Literal ID="ChatBoxesLiteralTop" runat="server" />
                    <asp:Literal ID="ChatBoxesLiteralMid" runat="server" />
                    <asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
                    <asp:Literal ID="ChatBoxesLiteralBot" runat="server" />
                    <div id="UserListCorner">
                        <img id="UserListBtn" src="images/list.png" />
                    </div>
                    <div id="UserList" class="UserListHidden">
                        <div id="UserListView">
                            <asp:Literal ID="UserListViewLiteral" runat="server" />
                        </div>
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>

代码背后:

protected void Panel3_Load(object sender, EventArgs e)
    {
        #region Ajax methods
        if (Request.Form["MethodName"] == "CreateChatBox")
        {
            CreateChatBox();
        }
        #endregion

        Engine m_engine = new Engine();
        string m_sql = @"SELECT FullName FROM Users WHERE RecordDeleted <> 1";
        DataTable dt = m_engine.GetObjectsAsDataTable(m_sql);
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            UserListViewLiteral.Text += "<div class='UserListEntry'><span class='UserListEntryStatus'><img src='images/status-online.png' width='10' /></span>&nbsp;<span class='UserListEntryName'>" + dt.Rows[i]["FullName"].ToString() + "</span></div>";
        }

        RadAjaxManager.GetCurrent(Page).ResponseScripts.Add("ChatAjax()");   
    }

    private void CreateChatBox()
    {
        ChatBoxesLiteralTop.Text = @"<div id='ChatBox' class='ChatBoxHidden'>
                                        <div class='ChatBoxHeader'>
                                            <img id='ChatBoxStatusBtn' src='Images/status-online.png' />
                                            <span id='ChatBoxUserLabel'>John Doe</span>
                                            <img id='closeBtn' src='Images/close.png' />
                                            <img id='toggleTab' src='Images/up-arrow.png' />
                                        </div>
                                        <div id='ChatBoxMessageOutput'></div><div class='ChatBoxFooter'>";

        TextBox txt = new TextBox();
        txt.ID = "ChatBoxMessageInput";
        txt.Height = 16;
        txt.MaxLength = 270;
        txt.Width = 250;
        txt.AutoPostBack = false;
        ChatBoxesPlaceHolder.Controls.Add(txt);

        RadButton btn = new RadButton();
        btn.ID = "ChatBoxSendButton";
        btn.Text = "Send";
        btn.AutoPostBack = true;
        btn.Height = 22;
        btn.Click += ChatBoxSendButton_Click;
        ChatBoxesPlaceHolder.Controls.Add(btn);

        ChatBoxesLiteralBot.Text = "</div></div>";

        Panel3.Update();

        RadAjaxManager.GetCurrent(Page).ResponseScripts.Add("ChatAjax()");
    }

我当然忽略了一些非常愚蠢的事情,但是来自经验丰富的 ASP.Net Ajaxer 的新眼睛将不胜感激!提前致谢。

澄清问题

有什么作用:

  • 代码运行正常。
  • JSON 方法被传递给后面的代码并被读取。
  • CreateChatBox() 方法贯穿并据称填充了文字和控件。
  • JSON 链中的所有回调均已成功执行。

什么不起作用:

  • UpdatePanel,即使在冗余回发之后,在代码成功执行后也没有这个新的 HTML。
4

1 回答 1

1

To Whom It May Concern


Well I happened to solve this problem the day after posting it. Of course there are now new hurdles to tackle but I am happy to say that my asynchronous chat module is nearly done. Since nobody decided to take on the problem, I am going to post what I did to properly produce dynamic, asynchronous objects based on hard-coded HTML in ASP.NET since, while Googling the matter, this post was the only relevant result popping up.

I'll start by saying I am well aware that this is a very unconventional approach. That being said, the requirements of the project justified the means. While there may be many other ways to accomplish your goal, this does work. I am not going to go into extraneous details with respect to my particular project, but hopefully this will help somebody in the future.

The Wrongs


The primary problem with my original question was the way I was attacking the rendering sequence. A major flaw in my logic was attempting to separate the ASP controls (literals, placeholders, buttons and such) from my HTML too much. My initial approach (from above) looked like this:

<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
            <ContentTemplate>
                <asp:Literal ID="ChatBoxesLiteralTop" runat="server" />
                <asp:Literal ID="ChatBoxesLiteralMid" runat="server" />
                <asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
                <asp:Literal ID="ChatBoxesLiteralBot" runat="server" />
                <div id="UserListCorner">
                    <img id="UserListBtn" src="images/list.png" />
                </div>
                <div id="UserList" class="UserListHidden">
                    <div id="UserListView">
                        <asp:Literal ID="UserListViewLiteral" runat="server" />
                    </div>
                </div>
            </ContentTemplate>
</asp:UpdatePanel>

The final result looks more like this:

<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
                    <div id="UserListCorner">
                        <img id="UserListBtn" src="images/list.png" />
                    </div>
                    <div id="UserList" class="UserListHidden">
                        <div id="UserListView">
                            <asp:Literal ID="UserListViewLiteral" runat="server" />
                        </div>
                    </div>
                    <asp:Label ID="Label42" Font-Bold="true" runat="server" />
                    <asp:HiddenField runat="server" ID="LatestDisplayTick" />
                </ContentTemplate>
</asp:UpdatePanel>

With the code behind (abridged) similar to this:

Literal top = new Literal();
// ...
UpdatePanel UpdatePanel2 = new UpdatePanel();
// ...
top.Text = @"<div id='ChatBox' class='ChatBoxShown'>
                                             <div class='ChatBoxHeader'>
                                                 <img id='ChatBoxStatusBtn' src='Images/status-online.png' />
                                                 <span id='ChatBoxUserLabel'>" + UserNames[0] + @"</span>
                                                 <img id='closeBtn' src='Images/close.png' />
                                                 <img id='toggleTab' src='Images/up-arrow.png' />
                                             </div>";

top.ID = "ChatBoxesLiteralTop";
top.Mode = LiteralMode.PassThrough;
// ...
UpdatePanel2.ID = "UpdatePanel2";
UpdatePanel2.UpdateMode = UpdatePanelUpdateMode.Conditional;
UpdatePanel2.ChildrenAsTriggers = false;
UpdatePanel2.ContentTemplateContainer.Controls.Add(top2);
// ...
Panel3.ContentTemplateContainer.Controls.Add(top);
Panel3.ContentTemplateContainer.Controls.Add(UpdatePanel2);               
Panel3.ContentTemplateContainer.Controls.Add(mid);

What It Means


All I've done is wrapped the entirety of my chatbox elements inside a single placeholder, dynamically creating HTML elements that wrap ASP controls all from the server and posting it as a "chunk" of dynamic data. This sidesteps some strange behaviors with ASP control placement otherwise, and allows for a quasi-OO approach for the client-side functionality of my project. After creation, I can now make use of some JSON and AJAX calls to dynamically enter data into said dynamically created controls.

An example would be posting a message received from a database notification to my chat window (ChatBoxesLiteralMid control) when it is received.

After Page/Control Load

if(ChatBoxesLiteralMid != null)
            ChatBoxesLiteralMid.Text += @"<div class='ChatBoxEntry'><span class='ChatBoxEntryName ChatBoxSelf'>" + AppParameters.Current.AppUser.FirstName + "</span>:&nbsp;<span class='ChatBoxEntryMessage'>" + dy.Rows[dy.Rows.Count - 1]["Message"].ToString() + "</span></div>";

Why Go To The Trouble?


What I have accomplished is for a particular project with needs to go far above and beyond the original scope, started by another developer years prior. This is an unconventional way to teach the old dog some new tricks. I now have near-full control of an indiscriminate amount of real-time chat boxes/sessions on the CLIENT side. It's really pretty freakin' sweet honestly. Please feel free to post questions (or concerns) as I regularly check SO and am happy to respond.

于 2013-03-28T19:37:41.080 回答