asp.net CompositeDataBoundControl用于单个对象

时间:2012-03-02 14:42:19

标签: c# asp.net

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

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

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

有没有办法为单个对象做同样的事情?

3 个答案:

答案 0 :(得分:4)

您需要覆盖 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

答案 1 :(得分:2)

如何创建控件列表,添加一个对象然后调用方法?

答案 2 :(得分:0)

我使用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的原因是因为它被设计为一次只显示一个项目。