使用 DataBinding 创建自定义控件

Create custom control with DataBinding

我创建了一个 SearchResults 控件来显示搜索结果。此控件有一个重复元素(显示结果),但也包含我为这个问题删除的其他元素。

当前在以下示例中 DataItem 无法解析。我正在尝试弄清楚如何使 DataItem 可解析,以便我可以按以下方式使用此控件:

<Controls:SearchResults runat="server" id="Results">
    <RowHeaderTemplate>
        <tr>
            <td>User ID</td>
        </tr>
    </RowHeaderTemplate>
    <RowItemTemplate>
        <tr>
            <td>
                <%#((Models.User)Container.DataItem).ID %>
            </td>
        </tr>
    </RowItemTemplate>
</Controls:SearchResults>

是这样使用的:

var searchResults = GetSearchResults();
Results.DataSource = searchResults ;
Results.DataBind();

搜索结果控制代码:

[System.ComponentModel.DefaultBindingProperty("DataSource")]
public partial class Search : UserControl
{
    [PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl))]
    public ITemplate RowHeaderTemplate { get; set; }

    [PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(TemplateControl))]
    public ITemplate RowItemTemplate { get; set; }

    public IEnumerable<object> DataSource { private get; set; }

    private bool DataBindingComplete { get; set; }

    public override void DataBind()
    {
        if (DataBindingComplete) return;
        foreach (var obj in DataSource)
        {
            var newControl = new PlaceHolder();
            RowItemTemplate.InstantiateIn(newControl);
            RowItemContainer.Controls.Add(newControl);
        }
        DataBindingComplete = true;
        base.DataBind();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Visible) return;

        OnInit(e);
        if (RowHeaderTemplate != null)
        {
            RowHeaderTemplate.InstantiateIn(RowHead);
        }
    }
}

带有标记:

<asp:PlaceHolder runat="server" ID="Wrapper">

    <h2>Results</h2>    
    <table border="1">
        <asp:PlaceHolder runat="server" ID="RowHead"/>
        <asp:Placeholder runat="server" Visible='<%#TotalResults == 0 %>'>
            <tr>
                <td colspan="100">
                    No results returned!
                </td>
            </tr>
        </asp:Placeholder>
        <asp:Placeholder runat="server" ID="RowItemContainer" Visible='<%#TotalResults > 0 %>'>

        </asp:PlaceHolder>        
    </table>

</asp:PlaceHolder>

请注意这是一个精简的示例,仅使用 Repeater 控件代替它是不够的。

问题是搜索控件的 RowItemTemplate 属性 的 TemplateContainer 属性引用了没有 DataItem 属性 的 TemplateControl。不使用 TemplateControl,而是创建一个具有 DataItem 属性:

的 SearchItem 控件
public class SearchItem : Control, INamingContainer
{
    public object DataItem { get; set; }
}

在搜索 class 中,更改 RowItemTemplate 属性 的 TemplateContainer 属性,使其引用 SearchItem 而不是 TemplateControl:

[PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(SearchItem))]
public ITemplate RowItemTemplate { get; set; }

此外,实例化 SearchItem 而不是 DataBind 中的 PlaceHolder:

var newControl = new SearchItem { DataItem = obj };

这些是让您的示例正常工作所需的最少更改。但是,您的自定义控件不会自动跨回发保留项目。要实现该功能,我建议您研究 Repeater class.

的源代码