我创建了一个ASP。. NET动态数据实体Web应用程序。我有一个外键包含6000+记录表。默认情况下,动态数据应用程序使用ForeignKey字段模板。
在编辑或插入模式下,ForeignKey字段模板会产生一个包含6000+项的下拉列表。这降低了性能,而且一点都不友好,所以我创建了一个自定义FieldTemplate来使用jquery自动完成和一个支持WCF REST的webservice返回json来填充自动完成列表,最多有25个项目。自定义字段模板包含2个文本框,一个用于名称,另一个用于id。id的文本框使用CSS隐藏。当在文本框中输入名称时,自动完成功能缩小了范围,并通过选择名称,使用javascript设置id。
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();
}
});
});
}
我使用ListView页面模板来显示、编辑和插入数据。页面模板由UpdatePanel和GridView以及FormView组成。在GridView中选择一条记录时,数据将显示在FormView中。FormView的默认模式被设置为编辑。当我开始输入名字时,一切正常。我可以选择其他值和更新等。到目前为止一切顺利。
我也有一个"插入新记录"的链接按钮位于更新面板。当点击此链接按钮时,FormView的FormViewMode被设置为插入。
protected void lnkInsertNew_Click(object sender, EventArgs e)
{
FormView1.ChangeMode(FormViewMode.Insert);
}
当在插入模式下,相同的自定义FieldTemplate被加载,但自动完成不再工作。我尝试了两种方法来重新启动自动完成功能。
我尝试的第一件事是:
if (Sys.WebForms) {
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function (sender, args) {
setAutoCompleteCustomerField();
});
}
第二:$(document).ready(function () {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(setAutoCompleteCustomerField);
});
两者都导致相同的行为。执行setAutoCompleteCustomerField函数。然而,执行似乎来得太早了。当我在setautocompleteccustomerfield函数中放置一个警告以显示客户名称的文本框的id时,显示的值为null。这表明该元素尚未加载。
alert($("#<%= txtCustomerName.ClientID %>").attr("id"));
我该如何克服这个问题?如何确保在调用setAutoCompleteCustomerField函数之前加载所有元素?提前感谢您的帮助!
添加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>
我找到了解决问题的办法。
我使用文本框的id启动自动补全:
$("input[id$='<%= txtCustomerName.ClientID %>']").autocomplete({...});
我将其更改为我在文本框上设置的某个css类,在本例中为artworkcopylookup。当我启动自动完成时,我使用css类来选择我的文本框:
$("input[class$='artworkcopylookup']").autocomplete({...});
脚本不是在id上搜索先前加载的文本框,而是搜索具有正确类集的任何输入。这样就可以找到新加载的文本框,并且一切都很顺利。