0

I created an ASP.NET Dynamic Data Entities Web Application. I have a foreign key to a table containing 6000+ records. By default this the Dynamic Data application uses the ForeignKey fieldtemplate.

When in edit or insert mode the ForeignKey fieldtemplate results in a dropdown with 6000+ items. This reduces performance and is not userfriendly at all, so I created a custom FieldTemplate to use jquery autocomplete and a WCF REST enabled webservice returning json to fill the autocomplete list with a maximum of 25 items. The custom fieldtemplate contains 2 textboxes, one for the name, the other one for the id. The textbox for the id is hidden using CSS. When typing in the textbox for the name the autocomplete function narrows down the scope and by selecting a name, the id is set using javascript.

function setAutoCompleteCustomerField() {
    if (!window.location.origin) window.location.origin = window.location.protocol + "//" + window.location.host;

    $(function () {
        $("input[id$='<%= txtCustomerName.ClientID %>']").autocomplete({
            source: function (request, response) {
                $.ajax({
                    url: window.location.origin + "/AutocompleteService.svc/CustomerLookup",
                    data: {
                        text: request.term,
                        count: 25
                    },
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    success: function (data) {
                        response($.map(data, function (item) {
                            return {
                                value: item.Name,
                                id: item.Id
                            }
                        }))
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        alert(errorThrown);
                    }
                });
            },
            minLength: 2,
            select: function (event, ui) {
                $("#<%= txtCustomerId.ClientID %>").val(ui.item.id);
                $("#<%= txtCustomerId.ClientID %>").change();
            }
        });
    });
}

I use the ListView pagetemplate to display, edit and insert data. The pagetemplate consists of an UpdatePanel with the GridView and the FormView. When selecting a record in the GridView the data is displayed in the FormView. The DefaultMode of the FormView is set to Edit. When I start typing in the name all works well. I can select other values and update etc. So far so good.

I also have an "Insert new record" linkbutton located within the updatepanel. When clicking this linkbutton, the FormViewMode of the FormView is set to Insert.

protected void lnkInsertNew_Click(object sender, EventArgs e)
{
    FormView1.ChangeMode(FormViewMode.Insert);
}

When in Insert mode the same custom FieldTemplate is loaded but the autocomplete is no longer working. I tried 2 methods to reinitiate the autocomplete functionality.

The first thing I tried was:

if (Sys.WebForms) {
    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function (sender, args) {
        setAutoCompleteCustomerField();
    });
}

The second:

$(document).ready(function () {
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(setAutoCompleteCustomerField);
});

Both resulted in the same behaviour. The setAutoCompleteCustomerField function is executed. However, it's seems that the execution comes to early. When I place an alert within the setAutoCompleteCustomerField function to display the id of the textbox for the customer name the value null is displayed. This indicates that the element is not yet loaded.

alert($("#<%= txtCustomerName.ClientID %>").attr("id"));

How can I overcome this issue? How can I make sure that all elements are loaded before calling the setAutoCompleteCustomerField function? Thanks in advance for you help!

UPDATE Added the code from ListDetails.aspx

<asp:Content ID="headContent" ContentPlaceHolderID="head" Runat="Server">
<% if (false) { %><script src="~/Scripts/jquery-1.5-vsdoc.js" type="text/javascript"></script><% } %>
</asp:Content>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <asp:DynamicDataManager ID="DynamicDataManager1" runat="server" AutoLoadForeignKeys="true">
        <DataControls>
            <asp:DataControlReference ControlID="FormView1" />
            <asp:DataControlReference ControlID="GridView1" />
        </DataControls>
    </asp:DynamicDataManager>

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
        <ContentTemplate>

            <div class="DD">               <asp:DynamicValidator runat="server" ID="GridViewValidator" ControlToValidate="GridView1" Display="None" CssClass="validator" />
                <asp:DynamicValidator runat="server" ID="FormViewValidator" ControlToValidate="FormView1" Display="None" CssClass="validator" />

                <div id="filterBox">
                <a href="#" id="filterToggle"><%= GalleryOnline.Globalization.Resources.Common.Label_ShowOrHideFilters %></a>
                    <div id="filters">
                    <asp:QueryableFilterRepeater runat="server" ID="FilterRepeater">
                        <ItemTemplate>
                            <span class="filterItem">
                            <asp:Label runat="server" Text='<%# Eval("DisplayName") %>' OnPreRender="Label_PreRender" />
                            <asp:DynamicFilter runat="server" ID="DynamicFilter" OnFilterChanged="DynamicFilter_FilterChanged" />
                            </span>
                        </ItemTemplate>
                    </asp:QueryableFilterRepeater>
                    </div>
                </div>
            </div>

            <asp:GridView ID="GridView1" runat="server" DataSourceID="GridDataSource" EnablePersistedSelection="true"
                AllowPaging="True" AllowSorting="True" OnDataBound="GridView1_DataBound" AutoGenerateSelectButton="true"
                OnRowEditing="GridView1_RowEditing" OnSelectedIndexChanging="GridView1_SelectedIndexChanging"
                OnRowDeleted="GridView1_RowDeleted" OnRowUpdated="GridView1_RowUpdated" ShowHeaderWhenEmpty="true"
                OnRowCreated="GridView1_RowCreated" CssClass="grid" OnPreRender="GridView1_PreRender"
                RowStyle-CssClass="td" HeaderStyle-CssClass="th" GridLines="None" AutoGenerateColumns="false">
                <PagerStyle CssClass="DDFooter" />
                <SelectedRowStyle CssClass="td selected" />
                <AlternatingRowStyle CssClass="td alternating" />
                <PagerTemplate>
                    <asp:GridViewPager runat="server" />
                </PagerTemplate>
                <EmptyDataTemplate>
                    <%= GalleryOnline.Globalization.Resources.Common.Message_NoData %>
                </EmptyDataTemplate>
            </asp:GridView>

            <div class="gridOptions">
                <asp:LinkButton ID="lnkInsertNew" runat="server" OnClick="lnkInsertNew_Click" CausesValidation="false">+ <%= GalleryOnline.Globalization.Resources.Common.InsertNewItem %></asp:LinkButton>
            </div> 

            <asp:EntityDataSource ID="GridDataSource" runat="server"/>

            <asp:QueryExtender ID="GridQueryExtender" TargetControlID="GridDataSource" runat="server">
                <asp:DynamicFilterExpression ControlID="FilterRepeater" />
            </asp:QueryExtender>

            <asp:Panel ID="DetailsPanel" runat="server" CssClass="tabs">
                <asp:FormView ID="FormView1" runat="server" DataSourceID="DetailsDataSource" RenderOuterTable="false"
                    OnPreRender="FormView1_PreRender" OnModeChanging="FormView1_ModeChanging" OnItemUpdated="FormView1_ItemUpdated"
                    OnItemInserted="FormView1_ItemInserted" OnItemDeleted="FormView1_ItemDeleted" OnDataBound="FormView1_DataBound" DefaultMode="Edit">
                    <ItemTemplate>
                        <asp:DynamicEntity runat="server" />
                        <div class="formActions">
                            <asp:Button runat="server" CommandName="Edit" Text="<%# GalleryOnline.Globalization.Resources.Common.Edit %>" />
                            <asp:Button runat="server" CommandName="Delete" Text="<%# GalleryOnline.Globalization.Resources.Common.Delete %>" OnClientClick='<%# "return confirm(\"" + GalleryOnline.Globalization.Resources.Common.Question_DeleteOrCancel +"\");" %>' />
                            <asp:Button runat="server" CommandName="New" Text="<%# GalleryOnline.Globalization.Resources.Common.New %>" />
                        </div>
                    </ItemTemplate>
                    <EditItemTemplate>
                        <asp:DynamicEntity runat="server" Mode="Edit" />
                        <div class="formActions">
                            <table border="0" cellpadding="0" cellspacing="0">
                                <tr>
                                    <td valign="top"><asp:Button runat="server" CommandName="Update" Text="<%# GalleryOnline.Globalization.Resources.Common.Update %>" ID="btnUpdate" /></td>
                                    <td valign="top"><asp:Button ID="Button5" runat="server" CommandName="Cancel" Text="<%# GalleryOnline.Globalization.Resources.Common.Cancel %>" CausesValidation="false" /></td>
                                    <td valign="top"><asp:Button ID="Button6" runat="server" CommandName="Delete" Text="<%# GalleryOnline.Globalization.Resources.Common.Delete %>" OnClientClick='<%# "return confirm(\"" + GalleryOnline.Globalization.Resources.Common.Question_DeleteOrCancel +"\");" %>' />  </td>
                                    <td valign="top"><asp:Button ID="Button7" runat="server" Text="<%# GalleryOnline.Globalization.Resources.Common.Back %>" CausesValidation="false" OnClientClick='javascript:history.go(-1);' /></td>
                                    <td>
                                        <div id="functionNavBox">
                                            <asp:Button id="btnFunctions" runat="server" OnClientClick="return false;" CssClass="functions" Text="<%# GalleryOnline.Globalization.Resources.Common.Functions %>" />
                                            <ul id="functionNavTree" style="display:none; position:relative; left:80px; bottom:103px; background-color:#fff; border:1px solid #CCC; padding:3px; z-index:1000;">
                                                <li><asp:Button id="Button3" runat="server" OnClientClick='<%# "window.open(\"" + GetRouteUrl("ViewInvoiceDetails", new {invoiceId=Eval("InvoiceId")}) + "\"); return false;" %>' Text="<%# GalleryOnline.Globalization.Resources.Common.PrintProFormaInvoice %>" /></li>
                                                <li><asp:Button ID="btnPrintInvoice" runat="server" CommandArgument='<%# Eval("InvoiceId") %>' OnClick="btnPrintInvoice_Click" OnClientClick='<%# "window.open(\"" + GetRouteUrl("ViewInvoiceDetails", new {invoiceId=Eval("InvoiceId")}) + "\");" %>' Text="<%# GalleryOnline.Globalization.Resources.Common.PrintInvoice %>" /></li>
                                                <li><asp:Button id="btnDelivered" runat="server" CommandArgument='<%# Eval("InvoiceId") %>' OnClick="btnDelivered_Click" Text="<%# GalleryOnline.Globalization.Resources.Common.Delivered %>" /></li>
                                                <li><asp:Button ID="Button2" runat="server" OnClientClick='<%# "window.open(\"" + GetRouteUrl("ViewValuation", new {invoiceId=Eval("InvoiceId")}) + "\"); return false;" %>' Text="<%# GalleryOnline.Globalization.Resources.Common.PrintValuation %>" /></li>
                                            </ul>
                                        </div>
                                    </td>
                                </tr>
                            </table>  
                        </div>
                    </EditItemTemplate>
                    <InsertItemTemplate>
                        <asp:DynamicEntity runat="server" Mode="Insert" />
                        <div class="formActions">
                            <asp:Button runat="server" CommandName="Insert" Text="<%# GalleryOnline.Globalization.Resources.Common.Insert %>" ID="btnInsert" />
                            <asp:Button runat="server" CommandName="Cancel" Text="<%# GalleryOnline.Globalization.Resources.Common.Cancel %>" CausesValidation="false" />
                        </div>
                    </InsertItemTemplate>
                </asp:FormView>

                <asp:Panel ID="InitialInvoiceItemDetailsPanel" runat="server" CssClass="extras" Visible="false">
                    <h4><%= String.Format(GalleryOnline.Globalization.Resources.Common.Label_CreatingInvoiceForArtworkCopy, this.ArtworkSalesPriceContext.Artwork.Name, this.ArtworkSalesPriceContext.CopyNumber) %></h4>
                    <table class="form">
                        <tr>
                            <td class="label"><%= GalleryOnline.Globalization.Resources.EntityMetadata.Price %></td>
                            <td class="value"><%= this.ArtworkSalesPriceContext.Price.ToString("F2") %></td>
                        </tr>
                        <tr>
                            <td class="label"><%= GalleryOnline.Globalization.Resources.EntityMetadata.VatPercentage %></td>
                            <td class="value"><asp:DropDownList ID="VatRateDropDown" runat="server" 
                                    DataValueField="VatPercentageId" DataTextField="Name" /></td>
                        </tr>
                    </table>
                </asp:Panel>

                <asp:EntityDataSource ID="DetailsDataSource" runat="server" EnableDelete="true" 
                    EnableInsert="true" EnableUpdate="true" 
                    oninserting="DetailsDataSource_Inserting" />

                <asp:QueryExtender TargetControlID="DetailsDataSource" runat="server">
                    <asp:ControlFilterExpression ControlID="GridView1" />
                </asp:QueryExtender>
            </asp:Panel>

        </ContentTemplate>
    </asp:UpdatePanel>
    <asp:UpdateProgress AssociatedUpdatePanelID="UpdatePanel1" runat="server" DisplayAfter="0" DynamicLayout="true" ID="UpdateProgress1" Visible="true">
    <ProgressTemplate>
        <div class="loadingProgress"><%# GalleryOnline.Globalization.Resources.Common.Label_Loading %></div>
    </ProgressTemplate>
    </asp:UpdateProgress>


    <script type="text/javascript">

        var gridSelectExtender = new GalleryOnline.UI.EasySelectGridViewExtender('<%= GridView1.ClientID %>', '<%= GridView1.UniqueID %>');

        if (Sys.WebForms)
        {
            Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function (sender, args)
            {
                if (args.get_panelsUpdated().length > 0)
                    gridSelectExtender.extend();

                GalleryOnline.UI.FilterManager.initializeFilters();
            });
        }

        $().ready(gridSelectExtender.extend);
        $().ready(GalleryOnline.UI.FilterManager.initializeFilterVisibility);

    </script>
</asp:Content>
4

1 回答 1

0

我找到了解决我的问题的方法。

我使用文本框的 id 启动了自动编译:

$("input[id$='<%= txtCustomerName.ClientID %>']").autocomplete({...});

我将其更改为我在文本框上设置的某个 css 类,在本例中为 artifactcopylookup。当我启动自动完成时,我使用 css 类来选择我的文本框:

$("input[class$='artworkcopylookup']").autocomplete({...});

该脚本不是在 id 上搜索先前加载的 texbox,而是搜索具有正确类集的任何输入。这样就可以找到新加载的 texbox 并且一切都像魅力一样工作。

于 2013-06-05T14:46:55.500 回答