使用DataBinding创建自定义控件

时间:2016-12-22 18:43:14

标签: c# asp.net data-binding webusercontrol

我创建了一个显示搜索结果的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控件代替它就不够了。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

var newControl = new SearchItem { DataItem = obj };

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