2009-06-03 126 views
8

我有一个相当大的asp.net网站,它使用GridView绑定到许多地方的同一个对象。我正在使用项目模板来自定义每一行。但是,为了在所有页面中具有相同的模板,我必须复制&将项目模板粘贴到每个页面。显然这不是最好的解决方案。除此之外,我希望能够通过更改一些配置文件来更改GridView使用的模板。 一种选择是使用DataGrid创建一个用户控件,并在每个页面中公开必要的属性。但是,这并不能满足第二个要求,即可以动态更改模板。 基本上我正在寻找一种方式来说GridView使用模板,并能够动态地做到这一点。任何想法都会有所帮助。动态更改GridView项目模板

+0

你想改变模板becoz你不同的设计模板? – 2009-06-03 13:02:26

+0

是的,我想要有不同的设计模板,并且能够动态地改变它们 – Albert 2009-06-03 13:19:56

回答

9

为了完成你想要什么,你有两个选择,因为我看到它:

1)动态地构建各自的TemplateField代码,并切换这些基础上进行一些配置。
2.)为您的自定义网格创建用户控件并使用它们。

我知道你说过你不想使用UserControl,因为这会消除你动态改变布局的能力,但让我用一个例子来挑战这个预设。

您可以利用内置的ASP.Net功能,通过使用PlaceHolder Control动态地将用户控件切换为自己喜欢的用户控件。

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

您的自定义网格可以在声明.ascx文件构建然后装就位在运行时动态像这样:现在

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

,如果你真的想使您的生活更轻松,那么你可以创建一个抽象的基类,所有您的自定义网格控件将继承。通过这种方式,可以在加载时对您的控件进行一般处理。

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

一个简单的网格可以在标记定义:

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

而你后面该控件的代码会是这个样子:

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

现在的页面或控制利用这只需要投射到基类,并且您可以一般使用它。以下是如何使用一个简单的例子,但我认为它使点明确:

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

所以,你有它。自定义模板化控件没有尝试在代码中手动构建它们的所有令人讨厌的头痛。我打算在另一个答案中发布完全手动的方式,但是一旦你看到它,我想你会同意这种方法是首选。

5

好的,所以这里是模板化字段示例的100%手动构建。

创建动态模板列的第一步是创建一个实现System.Web.UI.ITemplate接口的类。对于我们这里的简单示例,我只是要使用标签。

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

注意,为了支持数据绑定,你将不得不手动处理的任何控制(S)你选择添加事件。一旦你开发了你的模板,你就可以使用它作为你想要使用的任何TemplateField的ItemTemplate。

因此,假设我们有一些我们想要绑定网格的自定义业务对象的集合。

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

我们将不得不手动建立每个列作为TemplateField,然后将我们的集合绑定到GridView。为了使这种清洁和更容易的事,我都包裹着建造的模板列集合到一个静态辅助类:

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

在代码中使用这背后会是这个样子:

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

最后,这将产生一个与动态用户控件示例相同的输出,但正如您所看到的那样,它更麻烦。这也是一个非常简单的例子,它不包含任何CSS属性或多种类型的控件。你可以做到这一点,但这会很痛苦,并可能让你想要一起退出编程。使用用户控制解决方案,让您的生活更轻松。