asp.net CompositeDataBoundControl for a single object

本文关键字:single object for net CompositeDataBoundControl asp | 更新日期: 2023-09-27 18:26:22

我已经创建了一个CompositeDataBoundControl,我可以很好地对其进行数据绑定。现在我想做同样的事情,但不是针对对象列表,而是针对单个对象。原因是我希望我的同事能够简单地使用<%#Eval("X")%>在其前端代码中。

问题是CompositeDataBoundControl有一个我必须重写的方法,它只接受集合作为数据源

CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)

有没有一种方法可以对单个对象做同样的事情?

asp.net CompositeDataBoundControl for a single object

您需要覆盖DataSource属性

public class SingleObjectView : CompositeDataBoundControl
    {
        private object dataSource;
        public override object DataSource
        {
            get { return new List<object> { dataSource }; }
            set { dataSource = value; }
        }

        protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
        {
            SingleItem singleItem = null;
            if (dataBinding)
            {
                var it = dataSource.GetEnumerator();
                it.MoveNext();
                singleItem = new SingleItem(it.Current);
            }
            else
            {
                singleItem = new SingleItem(null);
            }
            ItemTemplate.InstantiateIn(singleItem);
            Controls.Add(singleItem);
            if (dataBinding)
                singleItem.DataBind();
            return 1;
        }

        [PersistenceMode(PersistenceMode.InnerProperty), TemplateContainer(typeof(SingleItem))]
        public ITemplate ItemTemplate { get; set; }
    }
    public class SingleItem : Control, IDataItemContainer
    {
        public SingleItem(object dataItem)
        {
            DataItem = dataItem;
        }
        public object DataItem { get; set; }
        public int DataItemIndex
        {
            get { return 0; }
        }
        public int DisplayIndex
        {
            get { return 0; }
        }
    }

编辑以显示用法

<ctrl:SingleObjectView ID="productView" runat="server">
   <ItemTemplate>
        <%# Eval("ProductName") %>
        <br />
        <%# Eval("Price","{0:c}") %>
   </ItemTemplate>
</ctrl:SingleObjectView>
 protected void Page_Load(object sender, EventArgs e)
 {
    if (!Page.IsPostBack)
      {
        productView.DataSource = new { ProductName="My Product", Price="10"};
        productView.DataBind();
      }
 }

因此,DataSource接收一个不实现IEnumerable的对象,但重写SingleObjectView控件的DataSource属性,确保调用CreateChildControls

创建一个控件列表,添加一个对象,然后调用该方法怎么样?

我使用FormView来允许对单个对象的实例进行模板化:

  protected void fvProduct_Init(object sender, EventArgs e)
  {
      // Load product template
      fvProduct.ItemTemplate = LoadTemplate("Templates/ProductTemplate.ascx");
      // Bind product to data source
      fvProduct.DataSource = new[] { Product };
      fvProduct.DataBind();
  }

然后在ProductTemplate.ascx中,你可以做这样的事情:

<h1><%# Eval("ProductName") %></h1>
<p><%# Eval("Description") %></p>
<h4><%# Eval("Price", "{0:C}")%></h4>

在你提到的场景中,你使用了一个自定义控件,但这个想法与上面的答案基本相同。您只需创建一个带有一个项的枚举并绑定它。使用FormView的原因是因为它被设计为一次只显示一个项。