2012-03-02 30 views
6

Tôi đã tạo ra một CompositeDataBoundControl mà tôi có thể databind hoàn toàn tốt. Bây giờ tôi muốn làm điều tương tự, nhưng không phải cho một danh sách các đối tượng, nhưng đối với một đối tượng duy nhất. Lý do là tôi muốn các đồng nghiệp của mình có khả năng chỉ cần sử dụng <% # Eval ("X")%> trong mã kết thúc trước của họ.asp.net CompositeDataBoundControl cho một đối tượng duy nhất

Vấn đề là các CompositeDataBoundControl có một phương pháp mà tôi phải ghi đè lên, mà chỉ chấp nhận một bộ sưu tập như một nguồn dữ liệu

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

Có cách nào để làm điều tương tự cho một đối tượng duy nhất?

Trả lời

4

Bạn cần phải ghi đè lên DataSource tài sản

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; } 
     } 
    } 

chỉnh sửa để hiển thị việc sử dụng

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

Vì vậy, các DataSource nhận một đối tượng mà không thực hiện IEnumerable, nhưng trọng các Thuộc tính DataSource của điều khiển SingleObjectView, đảm bảo rằng CreateChildControls được gọi.

+0

Đây chính xác là những gì TysHHTP đang cố gắng thực hiện. – AngeloBad

+0

@AngeloBad, kiểm soát này tôi đã viết được sử dụng như thế này: ctrlSingleObjectView.DataSource = singleObject; ctrlSingleObjectView.DataBind(); Tôi tin rằng đó chính xác là những gì OP cần. –

+0

Tôi muốn biết mặc dù tại sao câu trả lời này đã được giảm giá .. –

2

Điều gì tạo danh sách kiểm soát, thêm một đối tượng và sau đó gọi phương thức?

+1

Chúng tôi cũng đã tìm ra điều đó, nhưng nó cảm thấy như một giải pháp thay thế/hack hơn là một giải pháp tốt. – Tys

+1

Nếu một phương thức chấp nhận một IEnumerable làm tham số, chuyển một IEnumerable được tạo thành bởi chỉ 1 phần tử không phải là một hack. Bạn biết ý tôi là gì không? – AngeloBad

+2

Tôi đồng ý với AngeloBad. –

0

tôi sử dụng FormView để cho phép một thể hiện của một đối tượng duy nhất để được templated:

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

Sau đó, trong ProductTemplate.ascx bạn có thể làm những thứ như thế này:

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

Trong kịch bản của bạn, bạn nói bạn là sử dụng điều khiển tùy chỉnh nhưng ý tưởng về cơ bản giống như câu trả lời ở trên. Bạn chỉ cần tạo ra một enumerable với một mục và ràng buộc nó. Lý do sử dụng FormView là vì nó được thiết kế để chỉ hiển thị chính xác một mục tại một thời điểm.

Các vấn đề liên quan