简体   繁体   English

如何在客户端 JavaScript 中侦听服务器(代码隐藏)所做的 DOM 更改? (ASP.NET Framework 4.8 Web 应用程序)

[英]How to listen for DOM changes made by the server (code behind) in the client side JavaScript? (ASP.NET Framework 4.8 web application)

Context语境

I am working on a ASP.NET Framework 4.8 web application.我正在开发 ASP.NET Framework 4.8 Web 应用程序。

My Problem我的问题

I need to run a JavaScript function each time the server (code behind) changes the DOM, in this case adds- or removes rows from a Telerik RadGrid.每次服务器(背后的代码)更改 DOM 时,我都需要运行一个 JavaScript 函数,在这种情况下,从 Telerik RadGrid 添加或删除行。 I need some kind of listener on the client side or if there is a way in ASP.NET Framework 4.8 to notify the client.我在客户端需要某种侦听器,或者在 ASP.NET Framework 4.8 中有一种方法可以通知客户端。

Workflow and Steps工作流程和步骤

1: User clicks an "Add item"/"Remove item" link. 1:用户单击“添加项目”/“删除项目”链接。

2: The server (code behind) gets notified with an OnClick event. 2:服务器(代码隐藏)收到 OnClick 事件通知。 It adds or removes the item to a RadGrid.它将项目添加或删除到 RadGrid。

3: Now the JavaScript needs to know when the server (code behind) is done adding or removing that item. 3:现在 JavaScript 需要知道服务器(代码隐藏)何时完成添加或删除该项目。 How is this achieved?这是如何实现的?

Code代码

the .ascx code containing the RadGrid that the user selects items from:包含用户从中选择项目的 RadGrid 的 .ascx 代码:

<telerik:RadGrid ID="rgPlayers" CssClass="data-table bottomSpace" runat="server" AutoGenerateColumns="False" Skin="Metro" Height="288px"
                            ForeColor="#333333" CellPadding="4" ShowFooter="false" GridLines="None" AllowSorting="true"
                            OnSortCommand="rgPlayers_Sorting" OnNeedDataSource="rgPlayers_NeedDataSource" OnItemDataBound="rgPlayers_RowDataBound"
                             onkeydown="gridKeyDown(event);">
                            <ClientSettings Selecting-AllowRowSelect="true" EnablePostBackOnRowClick="false" AllowKeyboardNavigation="true">
                                <KeyboardNavigationSettings EnableKeyboardShortcuts="false" AllowSubmitOnEnter="false" AllowActiveRowCycle="true" />
                                <Scrolling SaveScrollPosition="true" AllowScroll="true" UseStaticHeaders="true"></Scrolling>
                            </ClientSettings>
                            <MasterTableView ShowHeadersWhenNoRecords="true" DataKeyNames="ToPlsyer, PlayerNr ">
                                <Columns>
                                    <telerik:GridTemplateColumn HeaderStyle-Width="150px">
                                        <HeaderTemplate>
                                            <table id="tablePlayerNr">
                                                <tr>
                                                    <td>
                                                        <asp:LinkButton ID="lbPlayerNumber" CommandName="Sort" CommandArgument="PlayerNr" runat="server" Text="<%$Resources:PlayerNr%>"></asp:LinkButton>
                                                    </td>
                                                </tr>
                                                <tr>
                                                    <td>
                                                        <asp:TextBox ID="tbPlayerNumberSearch" runat="server" CssClass="rightSpace" onkeypress="return tbPlayerNumberSearch()"></asp:TextBox>
                                                    </td>
                                                </tr>
                                            </table>
                                        </HeaderTemplate>
                                        <ItemTemplate>
                                            <asp:Label ID="lbLinkedPlayerNumber" runat="server" Text='<%# Bind("PlayerNr") %>'></asp:Label>
                                        </ItemTemplate>
                                    </telerik:GridTemplateColumn>

                                    <telerik:GridTemplateColumn HeaderStyle-Width="250px">
                                        <HeaderTemplate>
                                            <table id="tablePlayerDesc">
                                                <tr>
                                                    <td>
                                                        <asp:LinkButton ID="lbDescription" CommandName="Sort" CommandArgument="PlayerDescription" runat="server" Text="<%$Resources:Global, Description%>"></asp:LinkButton>
                                                    </td>
                                                </tr>
                                                <tr>
                                                    <td>
                                                        <asp:TextBox ID="tbDescriptionSearch" runat="server" CssClass="rightSpace" onkeypress="return tbDescriptionSearch()"></asp:TextBox>
                                                    </td>
                                                </tr>
                                            </table>
                                        </HeaderTemplate>
                                        <ItemTemplate>
                                            <asp:Label ID="lbLinkedPlayerDescription" runat="server" Text='<%# Bind("PlayerDescription") %>'></asp:Label>
                                        </ItemTemplate>
                                    </telerik:GridTemplateColumn>
                                    <telerik:GridNumericColumn DataFormatString="{0:F0}" HeaderStyle-Width="80px" ItemStyle-Width="80px" DataField="BalanceAvailable" HeaderText="<%$Resources:BalanceAvailable%>" AllowSorting="false"></telerik:GridNumericColumn>
                                    <telerik:GridTemplateColumn HeaderStyle-Width="100px" ItemStyle-Width="100px">
                                        <ItemTemplate>
                                            <asp:LinkButton ID="lbPlayerAdd" runat="server" Text="<%$ Resources:Global, Add%>" OnClick="btnAddLinkedPlayer_Click"></asp:LinkButton>
                                        </ItemTemplate>
                                    </telerik:GridTemplateColumn>
                                </Columns>
                            </MasterTableView>
                        </telerik:RadGrid>

The RadGrid taht the selected items are added to- or removed from when the user selects an item:当用户选择一个项目时,RadGrid taht 所选项目被添加到或删除:

<telerik:RadGrid ID="rgPlayers" CssClass="data-table bottomSpace" runat="server" AutoGenerateColumns="False" Skin="Metro" Height="200px" TabIndex="-1"
                            ForeColor="#333333" CellPadding="4" ShowFooter="false" GridLines="None" AllowAutomaticUpdates="true" AllowSorting="false"
                            OnItemDataBound="rgPlayers_RowDataBound" OnPreRender="rgPlayers_PreRender">
                            <ClientSettings Selecting-AllowRowSelect="true" Scrolling-SaveScrollPosition="true" Scrolling-AllowScroll="true" Scrolling-UseStaticHeaders="true">
                            </ClientSettings>
                            <MasterTableView ShowHeadersWhenNoRecords="true" TableLayout="Fixed" DataKeyNames="RowId">
                                <Columns>
                                    <telerik:GridBoundColumn DataField="RowId" />
                                    <telerik:GridBoundColumn DataField="SharedQuantity" />
                                    <telerik:GridBoundColumn HeaderStyle-Width="120px" DataField="PlayerNr" HeaderText="<%$Resources:PlayerNr%>" ReadOnly="True" />
                                    <telerik:GridBoundColumn HeaderStyle-Width="100%" ItemStyle-Width="100%" DataField="PlayerDescription" HeaderText="<%$Resources:Global, Description%>" ReadOnly="True" />
                                    <telerik:GridTemplateColumn HeaderStyle-Width="100px" ItemStyle-Width="100px">
                                        <HeaderTemplate>
                                            <asp:Label ID="lbHeaderQuantityText" runat="server" Text="<%$Resources:Global, Quantity%>"></asp:Label>
                                        </HeaderTemplate>
                                        <ItemTemplate>
                                            <asp:Label ID="lbQuantity" runat="server" Text='<%# Bind("Quantity") %>' CssClass="float-left" />
                                            <asp:ImageButton ID="btnAddQty" OnClick="btnAddQty_Click" CommandArgument='<%# Eval("RowId","{0}") %>' Height="18px" Width="18px" runat="server" CssClass="leftSpace float-left" ImageUrl="~/Images/plus.png" />
                                            <asp:ImageButton ID="btnRemoveQty" OnClick="btnRemoveQty_Click" CommandArgument='<%# Eval("RowId","{0}") %>' Height="18px" Width="18px" runat="server" CssClass="leftSpace float-left" ImageUrl="~/Images/minus.png" />
                                        </ItemTemplate>
                                    </telerik:GridTemplateColumn>

                                    <telerik:GridNumericColumn HeaderStyle-Width="60px" ItemStyle-Width="60px" FooterStyle-HorizontalAlign="Right" HeaderStyle-HorizontalAlign="Right" ItemStyle-HorizontalAlign="Right" DataField="PriceInclVat" DataFormatString="{0:F2}" HeaderText="<%$Resources:Global, UnitPriceColumn%>" ReadOnly="True" />
                                    <telerik:GridNumericColumn HeaderStyle-Width="75px" ItemStyle-Width="75px" DataField="Balance" DataFormatString="{0:F0}" HeaderText="<%$Resources:BalanceAvailable%>" ReadOnly="True" />

                                    <telerik:GridTemplateColumn HeaderText="<%$Resources:ToPlsyer%>" HeaderStyle-Width="100%" ItemStyle-Width="100%" UniqueName="PlayerNr" DataField="ToPlsyer">
                                        <ItemTemplate>
                                            <telerik:RadTextBox runat="server" CssClass="integer" Text='<%#Eval("ToPlsyer") %>' OnTextChanged="OnTextChanged" AutoPostBack="True" ID="MainPlayerTextbox" />
                                        </ItemTemplate>
                                    </telerik:GridTemplateColumn>

                                    <telerik:GridTemplateColumn HeaderStyle-Width="60px" ItemStyle-Width="80px">
                                        <ItemTemplate>
                                            <asp:LinkButton ID="lbRemove" CssClass="" runat="server" Text="<%$ Resources:Global, Delete%>" CommandArgument='<%# Eval("RowId","{0}") %>' OnClick="btnRemovePlayerItem_Click" />
                                        </ItemTemplate>
                                    </telerik:GridTemplateColumn>
                                </Columns>
                            </MasterTableView>
                        </telerik:RadGrid>

Method called in code behind when an "Add item" or "Remove item" link is clicked:单击“添加项目”或“删除项目”链接时在代码中调用的方法:

        protected async void btnAddLinkedPlayer_Click(object sender, EventArgs e)
        {
            ResetUnlinkedPlayerHtml();
            HideSearchPlayerhWarning();
            Player resultPlayer = null;
            string toPlayer = (string)((GridDataItem)((Control)sender).BindingContainer).GetDataKeyValue(nameof(Player.ToPlsyer));
            string playerNr = (string)((GridDataItem)((Control)sender).BindingContainer).GetDataKeyValue(nameof(Player.PlayerNr));

            if (!string.IsNullOrEmpty(playerNr))
            {
                resultPlayer = LinkedPlayers.Find(player => player.PlayerNr == playerNr);
            }

            if (resultPlayer != null)
            {
                PlayerOrderRow matchPlayer = PlayerOrderRows.Find(playerOrderRow => playerOrderRow.PlayerNr == resultPlayer.PlayerNr && playerOrderRow.ToPlsyer == toPlayer && resultPlayer.PlayerDescription == playerOrderRow.PlayerDescription && playerOrderRow.Unlinked == false);
                if (matchPlayer == null)
                {

                    try
                    {
                        resultPlayer.PriceInclVat = await GetPriceForPlayer(playerNr, 1, GetSetting().UserInformation, ddlDeliveryWH.SelectedItem.Value);
                    }
                    catch (Exception ex)
                    {
                        SetUserMessage(ex);
                    }

                    PlayerOrderRow row = new PlayerOrderRow(resultPlayer.PlayerNr, resultPlayer.PlayerDescription, 1, resultPlayer.BalanceAvailable, toPlayer, IsThisAWarrantyCase || IsThisAGoodwillCase ? 0 : resultPlayer.PriceInclVat, resultPlayer.PriceInclVat);
                    PlayerOrderRows.Add(row);
                }
                else
                {
                    matchPlayer.Quantity += 1;
                }

                BindSelectedPlayerOrderRowsToGrid(PlayerOrderRows, SessionConstants.CurrentPlayerNumber.TrimToEmpty(), SessionConstants.RepurchaseCaseReceipt);
            }
        }

Question and Final Thoughts问题和最后的想法

Is there any way for JavaScript on the client side to get notified when the server side (code behind) is done adding an item to the RadGrid?当服务器端(代码隐藏)完成向 RadGrid 添加项目时,客户端的 JavaScript 有什么方法可以得到通知吗?

Thanks!谢谢!

What do you mean notified that the server code is done?通知服务器代码完成是什么意思?

You can't run that server code behind as async.您不能以异步方式运行该服务器代码。 The event stub can CALL some other routine as async, but the server side code behind MUST ALWAYS 100% complete.事件存根可以异步调用其他一些例程,但背后的服务器端代码必须始终 100% 完成。

is there any way for JavaScript on the client side to get notified when the server side (code behind) is done当服务器端(代码隐藏)完成时,客户端的 JavaScript 有什么方法可以得到通知

You already know!!!你已经知道了!!! - if step one is to occur and run that event code behind, then that is HOW you know!!! - 如果第一步是发生并在后面运行该事件代码,那么您就知道了!!!

The code behind can't wait, nor can it run async.后面的代码不能等待,也不能异步运行。 Your code behind MUST ALWAYS 100% finish its code, and then the whole web page is sent down back to the client side.您背后的代码必须始终 100% 完成其代码,然后整个网页被发送回客户端。 the client side loads that whole page again, and then any JavaScript code such as page.load on OnReady starts running again.客户端再次加载整个页面,然后任何 JavaScript 代码(例如 OnReady 上的 page.load)再次开始运行。

So when you click a button?那么当你点击一个按钮时呢? The WHOLE page travels up to the web server.整个页面传送到 Web 服务器。 The web server then loads - gets that class object and initializes it from scratch.然后 Web 服务器加载 - 获取该类对象并从头开始对其进行初始化。 (the values and variables in the code start from scratch each time you click a button and post- bck). (每次单击按钮并回传时,代码中的值和变量都会从头开始)。

Your code behind then starts running and can ONLY modify that page in the very short time while the WHOLE web page is up on the server.然后您的代码开始运行,并且只能在整个网页在服务器上启动时在很短的时间内修改该页面。 When that code is done, the page THEN travels back to the client side.当该代码完成后,页面 THEN 返回到客户端。

Your code behind NEVER directly interacts with the user.您背后的代码永远不会直接与用户交互。 It ONLY can modify the web page during that short time or so called "round trip" in which the page is now up on the server.它只能在页面现在在服务器上启动的短时间内或所谓的“往返”期间修改网页。 This is also why your button click event code can't be async.这也是你的按钮点击事件代码不能异步的原因。 The code behind can change things on the web page, but the user will not see anything until such time the code behind is 100% finished.隐藏的代码可以更改网页上的内容,但在隐藏的代码 100% 完成之前,用户将看不到任何内容。 When that code behind is 100% done?当后面的代码 100% 完成时?

THEN AND ONLY then does that whole web page now make the trip back to the client side.然后,只有在那时,整个网页才会返回客户端。 Then client side renders the results, and the JavaScript routines are re-loaded and also start running.然后客户端呈现结果,JavaScript 例程被重新加载并开始运行。

Now the JavaScript needs to know when the server (code behind) is done adding or removing that item.现在 JavaScript 需要知道服务器(代码隐藏)何时完成添加或删除该项目。 How is this achieved?这是如何实现的?

Because step one occurred - that's how you know.因为第一步发生了 - 这就是你知道的。 If step one never occurs, then nothing else will occur.如果第一步永远不会发生,那么其他任何事情都不会发生。

There is no possible way for the code behind to modify anything on the web page unless the page MAKES the round trip up to the server.除非页面进行到服务器的往返,否则后面的代码不可能修改网页上的任何内容。 And that code behind can thus only change things in that very small window while the web page is up on the server.因此,当网页在服务器上时,隐藏的代码只能在那个非常小的窗口中更改内容。

So, you know if something changed if step 1 occurs and that post back occurs.因此,如果发生第 1 步并且发生回发,您就知道是否发生了某些变化。 The JavaScript running on client side?在客户端运行的 JavaScript? It not going to know until that post back and web page returns back to the client.它不会知道,直到回发和网页返回给客户端。 and when that occurs, the JavaScript is now starting over again - and only has the contents of the current page that just came back from the server - not the previous page and data - it is long gone.当这种情况发生时,JavaScript 现在重新开始 - 并且只有刚刚从服务器返回的当前页面的内容 - 而不是前一页和数据 - 它早已不复存在。 So there not a way to detect any changes, since you just sent a fresh whole new page back down to the client.所以没有办法检测任何更改,因为您只是将一个全新的全新页面发送回客户端。

Now you can on button click do a ajax call.现在您可以单击按钮进行 ajax 调用。 That means NO round trip, and no page post back.这意味着没有往返,也没有页面回传。 But then again, when you make such calls, then that code behind can't update the web page.但是话又说回来,当您进行此类调用时,后面的代码无法更新网页。 You would have to write JavaScript code to get the results and re-plot the grid client side.您必须编写 JavaScript 代码才能获得结果并重新绘制网格客户端。 but I don't see why just using code behind and the button click as the trigger to "assume" that the grid will have changed.但我不明白为什么只使用背后的代码和按钮单击作为触发器来“假设”网格将发生变化。 I mean, unless the user clicks a button, then the grid not going to change, is it?我的意思是,除非用户点击按钮,否则网格不会改变,是吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法将Javascript客户端对HTML属性所做的更改读取到ASP.NET服务器端 - Unable to read changes made in HTML attribute on client Side by Javascript to ASP.NET server side 检测客户端DOM更改ASP.NET中的服务器端:是否可能? - Detecting client-side DOM changes server-side in ASP.NET: Is It Possible? 从asp.net后面的代码为客户端编码 - Coding for client side from code behind in asp.net 服务器端代码执行后,从asp.net代码中调用javascript函数 - Call javascript function from asp.net code behind after server side code executes 如何使用c#将服务器端处理的数据从代码隐藏添加到asp.net中.aspx页面中的javascript - How to add server-side processed data from code-behind to javascript in .aspx page in asp.net using c# 使用 C# 将在 JavaScript 中创建的变量值传递到 ASP.Net 中的服务器端(代码隐藏) - Pass the variable values created in JavaScript to Server Side (Code Behind) in ASP.Net using C# 如何在asp.net中从javascript调用服务器端代码? - How to call server side code from javascript in asp.net? 如何从asp.net中的代码引发客户端“重置”按钮的点击事件? - How to raise click event of a client side `reset ` button from code behind in asp.net? 如何将数组从Asp.net服务器端传递到客户端的Javascript函数 - How to pass array from Asp.net server side to Javascript function on client side 在ASP.NET中,如何使用一个表单提交在客户端(javascript)和服务器端处理数据? - In ASP.NET, how to process data on both client side (javascript) and server side with the one form submission?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM