2009-06-03 31 views
8

Tôi có một trang web asp.net khá lớn sử dụng GridView ràng buộc với cùng một đối tượng ở nhiều nơi. Tôi đang sử dụng một mẫu mục để tùy chỉnh từng hàng. Tuy nhiên để có cùng một mẫu trong tất cả các trang, tôi phải sao chép & dán mẫu mục vào mỗi trang. Rõ ràng đây không phải là giải pháp tốt nhất. Ngày đầu này tôi muốn có thể thay đổi các mẫu được sử dụng bởi GridView, bằng cách thay đổi một số tập tin cấu hình. Một tùy chọn sẽ là tạo điều khiển người dùng với DataGrid và hiển thị các thuộc tính cần thiết được sử dụng trong mỗi trang. Tuy nhiên, điều này không đáp ứng yêu cầu thứ hai để có thể tự động thay đổi mẫu. Về cơ bản tôi đang tìm một cách để nói với GridView để sử dụng một mẫu và có thể làm điều này một cách linh hoạt. Bất kỳ ý tưởng nào cũng hữu ích.Tự động thay đổi mục GridView mẫu

+0

bạn có muốn thay đổi mẫu becoz bạn thiết kế mẫu khác không? –

+0

vâng, tôi muốn có các mẫu thiết kế khác nhau và có thể thay đổi chúng động – Albert

Trả lời

9

Để thực hiện những gì bạn muốn, bạn có hai lựa chọn như tôi nhìn thấy nó:

1.) Xây dựng mỗi TemplateField động trong mã, và chuyển đổi các dựa trên một số cấu hình.
2.) Tạo điều khiển người dùng cho lưới tùy chỉnh của bạn và sử dụng các tùy chọn đó.

Tôi biết bạn đã nói bạn không muốn sử dụng UserControl vì điều đó sẽ lấy đi khả năng của bạn để tự động thay đổi bố cục của bạn, nhưng hãy để tôi thử thách giả định đó bằng một ví dụ.

Bạn có thể sử dụng tính năng ASP.Net tích hợp sẵn để tự động tắt điều khiển người dùng theo ý thích của mình bằng cách sử dụng PlaceHolder Control.

<asp:PlaceHolder ID="GridViewPlaceHolder" runat="server" /> 

lưới tùy chỉnh của bạn có thể được xây dựng khai báo trong file ascx và sau đó nạp vào vị trí tự động trong thời gian chạy như vậy:

GridViewPlaceHolder.Controls.Add(LoadControl("~/Controls/MyCustomControl.ascx")); 

Bây giờ, nếu bạn thực sự muốn làm cho cuộc sống của bạn dễ dàng hơn, sau đó bạn có thể tạo một lớp cơ sở trừu tượng mà tất cả các điều khiển lưới tùy chỉnh của bạn sẽ kế thừa từ đó. Bằng cách này, các điều khiển của bạn có thể được xử lý chung khi được nạp.

public abstract class CustomGridControl: System.Web.UI.UserControl 
{ 
    public abstract Object DataSource { get; set; } 
} 

Một lưới đơn giản có thể được xác định trong đánh dấu:

<asp:GridView ID="myGridView" runat="server" AutoGenerateColumns="false"> 
    <Columns> 
     <asp:TemplateField HeaderText="Name"> 
      <ItemTemplate> 
       <asp:Label Text='<%#Eval("Name") %>' runat="server"></asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Age"> 
      <ItemTemplate> 
       <asp:Label Text='<%#Eval("Age") %>' runat="server"></asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

Và mã của bạn đằng sau để kiểm soát đó sẽ giống như thế này:

public partial class SimpleGrid : CustomGridControl 
{ 
    public override object DataSource 
    { 
     get { return myGridView.DataSource; } 
     set { myGridView.DataSource = value; } 
    } 
} 

Bây giờ, trang hoặc kiểm soát mà sử dụng điều này chỉ có để đúc đến lớp cơ sở, và bạn có thể sử dụng nó một cách tổng quát. Sau đây là một ví dụ đơn giản về cách bạn có thể sử dụng điều này, nhưng tôi nghĩ điều đó làm cho điểm rõ ràng:

protected void Page_Load(object sender, EventArgs e) 
{ 
    var dataSource = new List<MyCustomClass> 
         { 
          new MyCustomClass{Name = "Josh", Age = 43}, 
        new MyCustomClass{Name = "Bob", Age = 14}, 
        new MyCustomClass{Name = "Ashley", Age = 32}, 
         }; 

    DynamicallyLoadUserControlGrid("~/GridViewTemplates/SimpleGrid.ascx", dataSource); 
} 

private void DynamicallyLoadUserControlGrid(String controlLocation, List<MyCustomClass> dataSource) 
{ 
    var ctrl = (CustomGridControl)LoadControl(controlLocation); 
    ctrl.DataSource = dataSource; 
    ctrl.DataBind(); 

    GridViewPlaceHolder.Controls.Add(ctrl); 
} 

Vì vậy, bạn có nó. Tùy chỉnh templated điều khiển mà không có tất cả các nhức đầu khó chịu của cố gắng để xây dựng tất cả lên bằng tay trong mã. Tôi sẽ đăng hoàn toàn thủ công cách làm điều này trong câu trả lời khác, nhưng một khi bạn nhìn thấy nó, tôi nghĩ bạn sẽ đồng ý rằng phương pháp này được ưa thích.

+0

Tăng bạn rất nhiều, nó hoạt động rất tốt sau khi tôi hiểu điểm :) –

5

Được rồi, vì vậy, đây là ví dụ về cách xây dựng các trường mẫu theo cách thủ công 100%.

Bước đầu tiên trong việc tạo cột mẫu động là tạo lớp học triển khai giao diện System.Web.UI.ITemplate. Ví dụ đơn giản của chúng tôi ở đây, tôi sẽ sử dụng một nhãn.

public class MyCustomTemplate : ITemplate 
{ 
    public String DataField { get; set; } 

    public MyCustomTemplate(String dataField) 
    { 
     DataField = dataField; 
    } 

    public void InstantiateIn(Control container) 
    { 
     var label = new Label(); 
     label.DataBinding += label_DataBinding; 

     container.Controls.Add(label); 
    } 

    void label_DataBinding(object sender, EventArgs e) 
    { 
     var label = (Label)sender; 
     var context = DataBinder.GetDataItem(label.NamingContainer); 
     label.Text = DataBinder.Eval(context, DataField).ToString(); 
    } 
} 

Lưu ý rằng để hỗ trợ DataBinding, bạn sẽ phải xử lý thủ công sự kiện đó trên bất kỳ điều khiển nào bạn chọn thêm. Khi bạn đã phát triển mẫu của mình, bạn có thể sử dụng mẫu này làm ItemTemplate cho bất kỳ TemplateField nào mà bạn muốn sử dụng.

Vì vậy, giả sử chúng tôi có một số bộ sưu tập các đối tượng kinh doanh tùy chỉnh mà chúng tôi muốn ràng buộc lưới của chúng tôi.

public class MyCustomClass 
{ 
    public String Name { get; set; } 
    public Int32 Age { get; set; } 
} 

Chúng ta sẽ phải tự xây dựng mỗi cột là một TemplateField, và sau đó gắn bộ sưu tập của chúng tôi để các GridView. Để làm điều này sạch hơn và dễ dàng hơn để làm, tôi đã gói gọn việc xây dựng bộ sưu tập TemplateField vào một lớp helper tĩnh:

public static class MyCustomTemplateCollection 
{ 
    public static DataControlFieldCollection GetTemplateCollection() 
    { 
     var col = new DataControlFieldCollection(); 

     var nameField = new TemplateField 
         { 
          HeaderText = "Name", 
          ItemTemplate = new MyCustomTemplate("Name") 
         }; 

     var ageField = new TemplateField 
         { 
          HeaderText = "Age", 
          ItemTemplate = new MyCustomTemplate("Age") 
         }; 

     col.Add(nameField); 
     col.Add(ageField); 

     return col; 
    } 
} 

Sử dụng điều này trong mã của bạn đằng sau sẽ giống như thế này:

protected void Page_Load(object sender, EventArgs e) 
{ 
    var dataSource = new List<MyCustomClass> 
         { 
          new MyCustomClass{Name = "Josh", Age = 43}, 
        new MyCustomClass{Name = "Bob", Age = 14}, 
        new MyCustomClass{Name = "Ashley", Age = 32}, 
         }; 

    DynamicGrid(dataSource); 
} 

private void DynamicGrid(List<MyCustomClass> dataSource) 
{ 
    var col = MyCustomTemplateCollection.GetTemplateCollection(); 

    foreach (DataControlField field in col) 
    { 
     myGridView.Columns.Add(field); 
    } 

    myGridView.DataSource = dataSource; 
    myGridView.DataBind(); 
} 

Cuối cùng, điều này sẽ tạo ra một đầu ra giống hệt với ví dụ kiểm soát người dùng động, nhưng như bạn có thể thấy, nó sẽ phức tạp hơn nhiều. Đây cũng là một ví dụ rất đơn giản không bao gồm bất kỳ thuộc tính CSS nào hoặc nhiều loại điều khiển. Bạn có thể làm điều này, nhưng nó sẽ gây đau đớn và có thể khiến bạn muốn bỏ chương trình cùng nhau. Đi với giải pháp kiểm soát người dùng và làm cho cuộc sống của bạn dễ dàng hơn.

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