Динамично измените шаблон объекта GridView

Еще одна приятная версия в VB.NET, если кому-то интересно! Пришлось использовать функцию пола для правильного округления.

 Public Function NumberToText(n As Integer) As String
        Dim a As String() = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"}
        Dim tens As String() = {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy",
         "Eighty", "Ninety"}

        If (n < 0) Then
            Return "Minus " + NumberToText(-n)
        ElseIf (n = 0) Then
            Return ""
        ElseIf (n <= 19) Then
            Return a(n - 1) + " "
        ElseIf (n <= 99) Then
            Return tens(Math.Floor(n / 10) - 2) + " " + NumberToText(n Mod 10)
        ElseIf (n <= 199) Then
            Return "One Hundred " + NumberToText(n Mod 100)
        ElseIf (n <= 999) Then
            Return NumberToText(Math.Floor(n / 100)) + "Hundreds " + NumberToText(n Mod 100)
        ElseIf (n <= 1999) Then
            Return "One Thousand " + NumberToText(n Mod 1000)
        ElseIf (n <= 999999) Then
            Return NumberToText(Math.Floor(n / 1000)) + "Thousands " + NumberToText(n Mod 1000)
        ElseIf (n <= 1999999) Then
            Return "One Million " + NumberToText(n Mod 1000000)
        ElseIf (n <= 999999999) Then
            Return NumberToText(Math.Floor(n / 1000000)) + "Millions " + NumberToText(n Mod 1000000)
        ElseIf (n <= 1999999999) Then
            Return "One Billion " + NumberToText(n Mod 1000000000)
        Else
            Return NumberToText(Math.Floor(n / 1000000000)) + "Billions " + NumberToText(n Mod 1000000000)
        End If

    End Function
8
задан Albert 3 June 2009 в 11:27
поделиться

2 ответа

Для того, чтобы выполнить то, что вы хотите, у вас есть два варианта, как я это вижу:

1.) Создайте каждое TemplateField динамически в коде и переключайте их в зависимости от конфигурации.
2.) Создайте пользовательские элементы управления для своих пользовательских сеток и используйте их вместо них.

Я знаю, что вы сказали, что не хотите использовать UserControl, потому что это лишит вас возможности динамически изменять макет, но позвольте мне оспорить это предположение с примером.

Вы можете использовать встроенные функции ASP.Net, чтобы динамически переключать пользовательские элементы управления по своему вкусу, используя Элемент управления PlaceHolder .

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

Итак, вот оно. Пользовательские шаблоны элементов управления без всякой неприятной головной боли, связанной с попытками создать их вручную в коде. Я собираюсь опубликовать полностью ручной способ сделать это в другом ответе, но как только вы его увидите, я думаю, вы согласитесь, что этот метод предпочтительнее.

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

Итак, вот оно. Пользовательские шаблоны элементов управления без всякой неприятной головной боли, связанной с попытками создать их вручную в коде. Я собираюсь опубликовать полностью ручной способ сделать это в другом ответе, но как только вы его увидите, я думаю, вы согласитесь, что этот метод предпочтительнее.

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

Итак, вот оно. Пользовательские шаблоны элементов управления без всякой неприятной головной боли, связанной с попытками создать их вручную в коде. Я собираюсь опубликовать полностью ручной способ сделать это в другом ответе, но как только вы его увидите, я думаю, вы согласитесь, что этот метод предпочтительнее.

9
ответ дан 5 December 2019 в 12:12
поделиться

Хорошо, вот пример 100% ручного создания шаблонных полей.

Первым шагом в создании динамических столбцов шаблона является создание класса, реализующего систему . Интерфейс 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 вам придется вручную обрабатывать это событие для любых элементов управления, которые вы решите добавить. После того, как вы разработали свой шаблон, вы можете использовать его как свой ItemTemplate для любого TemplateField, который вы хотите использовать.

Итак, предположим, что у нас есть некоторая коллекция настраиваемых бизнес-объектов, к которым мы хотим привязать нашу сетку.

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 или нескольких типов элементов управления. Вы могли бы это сделать, но это будет болезненно и может заставить вас отказаться от программирования полностью. Используйте решение для управления пользователем и сделайте себе жизнь проще.

это даст результат, идентичный примеру динамических пользовательских элементов управления, но, как вы можете видеть, это намного более громоздко. Это также очень упрощенный пример, который не включает никаких атрибутов CSS или нескольких типов элементов управления. Вы могли бы это сделать, но это будет болезненно и может заставить вас отказаться от программирования полностью. Используйте решение для управления пользователем и сделайте себе жизнь проще.

это даст результат, идентичный примеру динамических пользовательских элементов управления, но, как вы можете видеть, это намного более громоздко. Это также очень упрощенный пример, который не включает никаких атрибутов CSS или нескольких типов элементов управления. Вы могли бы это сделать, но это будет болезненно и может заставить вас отказаться от программирования полностью. Используйте решение для управления пользователем и сделайте себе жизнь проще.

5
ответ дан 5 December 2019 в 12:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: