ExtenderControl не работает должным образом
Я пытаюсь сделать свою собственную версию контроля повторителя. Это не DataBoundControl; он не будет привязан к DataSource, DataSourceID, методу DataBind и т. д. и т. д. Он имеет вложенный в него шаблон и свойство, называемое RepeatCount
и он будет повторять все, что находится внутри шаблона, как указано вышеупомянутым свойством.
Однако, если вы добавите текстовое поле и расширитель автозаполнения, связанный с ним внутри шаблона, функция автозаполнения будет нарушена. Вот изображение, показывающее поток проблем:
Обратите внимание на сгенерированные идентификаторы текстового поля. Все, что я добавил, это TextBox с
ID="TextBox1"
внутри шаблона, но одно и то же имя / идентификатор повторяется несколько раз.Вы можете видеть, что текстовое поле видно. Чтобы понять, почему он виден, посмотрите в коде позади и просмотрите событие ItemPreRender.
Я обработал (на странице aspx). Если бы я не написал такой код, я бы получил исключение, говорящее:
- Однако написание кода, упомянутого в pt2, никуда меня не приведет. Функция автозаполнения не работает должным образом.
В чем может быть проблема здесь? Если бы это было должным образом помещено в управление повторителем и настроено на работу подобным образом, это работало бы...
Так чего мне здесь не хватает?
Вот части исходного кода, которым я делюсь:
страница ASPX
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MyRepeaterComplex.aspx.cs" Inherits="RelationalGridView.Web.MyRepeaterComplex" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc2" %>
<%@ Register Assembly="WebGui.Extensions" Namespace="WebGui.Extensions.MyRepeater"
TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>MyRepeater Sample</title>
<style type="text/css">
/*AutoComplete flyout */
.autocomplete_completionListElement
{
margin : 0px!important;
background-color : inherit;
color : windowtext;
border : buttonshadow;
border-width : 1px;
border-style : solid;
cursor : 'default';
overflow : auto;
height : 200px;
text-align : left;
list-style-type : none;
}
/* AutoComplete highlighted item */
.autocomplete_highlightedListItem
{
background-color: #ffff99;
color: black;
padding: 1px;
}
/* AutoComplete item */
.autocomplete_listItem
{
background-color : window;
color : windowtext;
padding : 1px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<cc1:MyRepeater ID="MyRepeater1" runat="server" RepeatCount="10">
<Template>
<p>Enter Name: <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></p>
<cc2:AutoCompleteExtender
ID="AutoCompleteExtender1"
runat="server"
TargetControlID="TextBox1"
ServicePath="AutoComplete.asmx"
ServiceMethod="GetCompletionList"
MinimumPrefixLength="2"
CompletionInterval="1000"
EnableCaching="true"
CompletionSetCount="20"
CompletionListCssClass="autocomplete_completionListElement"
CompletionListItemCssClass="autocomplete_listItem"
CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem"
DelimiterCharacters=";, :"
ShowOnlyCurrentWordInCompletionListItem="true">
</cc2:AutoCompleteExtender>
</Template>
</cc1:MyRepeater>
</div>
</form>
</body>
</html>
Код Apsx Позади:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
namespace RelationalGridView.Web
{
public partial class MyRepeaterComplex : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//MyRepeater1.ItemPreRender += new WebGui.Extensions.MyRepeater.MyRepeaterItemPreRenderDelegate(MyRepeater1_ItemPreRender);
}
protected void MyRepeaterItemPrerender(object sender, WebGui.Extensions.MyRepeater.MyRepeaterItemEventArgs e)
{
TextBox tbx = (TextBox)e.Container.FindControl("TextBox1");
AutoCompleteExtender ace = (AutoCompleteExtender)e.Container.FindControl("AutoCompleteExtender1");
ScriptManager.GetCurrent(this).RegisterExtenderControl(ace, tbx);
}
}
}
Код для MyRepeater
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Collections;
namespace WebGui.Extensions.MyRepeater
{
public delegate void MyRepeaterItemPreRenderDelegate(object sender, MyRepeaterItemEventArgs e);
public class MyRepeater: WebControl
{
List<Control> Containers;
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(MyRepeaterTemplateContainer))]
public ITemplate Template { get; set; }
public event MyRepeaterItemPreRenderDelegate ItemPreRender;
public MyRepeater()
{
RepeatCount = 0;
Containers = new List<Control>();
}
public int RepeatCount { get; set; }
protected override void OnPreRender(EventArgs e)
{
MyRepeaterItemEventArgs ex = new MyRepeaterItemEventArgs();
for (int i = 0; i < RepeatCount; i++)
{
MyRepeaterTemplateContainer container = new MyRepeaterTemplateContainer();
container.Page = Page;
Template.InstantiateIn(container);
if (ItemPreRender != null)
{
ex.Container=container;
ItemPreRender(this, ex);
}
Containers.Add(container);
}
}
protected override void Render(HtmlTextWriter writer)
{
foreach (Control ctrl in Containers)
{
ctrl.RenderControl(writer);
writer.WriteLine();
}
}
}
}
1 ответ
Вместо того, чтобы создавать экземпляр шаблона в методе OnPreRender, вам нужно использовать метод CreateChildControls. Этот метод используется для создания дочернего контроля. Причиной проблемы является то, что ваш экстендер добавлен в коллекцию элементов управления слишком поздно в жизненном цикле страницы, и поэтому он не может быть зарегистрирован.
Я могу посоветовать использовать Composite control в качестве базового вместо WebControl. У Дино Эспозито есть очень хорошая статья, связанная с этой областью: http://msdn.microsoft.com/en-us/library/aa479016.aspx.
Еще одно замечание: если вы создаете пользовательский серверный элемент управления, унаследованный от WebControl, и хотите, чтобы два экземпляра в одном и том же контейнере именования (например, страница или т. Д.) Имели разные идентификаторы дочерних элементов управления, то вам нужно пометить свой пользовательский элемент управления с помощью интерфейса INamingContainer. Дополнительную информацию можно найти в этой статье: http://msdn.microsoft.com/en-us/library/system.web.ui.inamingcontainer.aspx