【问题标题】:Dynamically change GridView item template动态更改 GridView 项模板
【发布时间】:2010-10-30 23:05:09
【问题描述】:

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

【问题讨论】:

  • 你想改变模板,因为你不同的设计模板?
  • 是的,我想拥有不同的设计模板并能够动态更改它们

标签: asp.net gridview dynamic templates


【解决方案1】:

为了完成你想要的,在我看来,你有两个选择:

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

所以,你有它。自定义模板控件,无需尝试在代码中手动构建它们。我将在另一个答案中发布完全手动的方法,但是一旦你看到它,我想你会同意这种方法是首选的。

【讨论】:

  • 非常感谢你,在我明白了这一点之后,它工作得很好:)
【解决方案2】:

好的,下面是 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();
    }
}

请注意,为了支持 DataBinding,您必须在选择添加的任何控件上手动处理该事件。开发模板后,您可以将其用作您想要使用的任何 TemplateField 的 ItemTemplate。

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

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

我们将不得不手动将每一列构建为一个 TemplateField,然后将我们的集合绑定到 GridView。为了让这个更干净更容易做,我将 TemplateField 集合的构建封装到一个静态帮助器类中:

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 属性或多种类型的控件。你可以这样做,但这会很痛苦,并且可能会让你想一起退出编程。使用用户控制解决方案,让您的生活更轻松。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多