1

我正在尝试制作自己的中继器控件版本。它不是 DataBoundControl;它不会绑定到 DataSource、DataSourceID、DataBind 方法等。它有一个嵌套在其中的模板,以及一个名为 的属性RepeatCount,它将重复上述属性指定的模板内的任何内容。

但是,如果您在模板中添加一个文本框和一个与之关联的自动完成扩展器,那么自动完成的功能就会被破坏。这是一张显示大量问题的图片:

在此处输入图像描述

  • 注意生成的文本框 ID。我添加的只是 ID="TextBox1"模板内部的一个文本框,但相同的名称/ID 重复了多次。

  • 您可以看到文本框是可见的。要了解它为何可见,请查看后面的代码并查看
    我已处理的 ItemPreRender 事件(在 aspx 页面上)。如果我没有编写这样的代码,我会得到一个异常说:

在此处输入图像描述

  • 然而,在 pt2 中提到的编写代码并没有让我有任何收获。自动完成功能无法正常工作。

这里可能是什么问题?如果将其正确放入中继器控件并以类似的方式工作,它将起作用...

那么我在这里错过了什么?

以下是我分享的部分源代码:

页面

<%@ 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();
            }
        }
    }
}
4

1 回答 1

0

Instead of instantiating your template in OnPreRender method you need to use CreateChildControls method. This method is used to create child control. The cause of the problem is that your extender is added to controls collection too late in Page life cycle and that's why it can't be registered.

I can advise to use Composite control as base one instead of WebControl. Dino Esposito has a very good article related to this area: http://msdn.microsoft.com/en-us/library/aa479016.aspx.

还有一点需要注意:如果您创建从 WebControl 继承的自定义服务器控件,并希望同一命名容器(如页面等)中的两个实例具有不同的子控件 ID,那么您需要使用 INamingContainer 接口标记您的自定义控件。更多信息可以在这篇文章中找到:http: //msdn.microsoft.com/en-us/library/system.web.ui.inamingcontainer.aspx

于 2012-11-23T19:02:32.417 回答