为了完成你想要的,在我看来,你有两个选择:
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);
}
所以,你有它。自定义模板控件,无需尝试在代码中手动构建它们。我将在另一个答案中发布完全手动的方法,但是一旦你看到它,我想你会同意这种方法是首选的。