Search code examples
c#asp.netgridviewdynamic-data

Gridview from checkboxlist


I have a dynamically created Checkboxlist ( I am using Dynamic Data and I am talking about the Many-to-many_edit.aspx ). I have like 20 000+ item added in my Checkboxlist and I need pagination for this.

I thought binding this checkboxlist to a gridview would do the trick? How can I do this ?

EDIT: I've read a lot about this subject but I couldn't find anything good . When I try to put Checkboxlist's source in my GridView.DatSource it throws OutOfMemory exception

EDIT2: I am trying something like this, but now, because my checkboxlist it's inside the gridview I don't know how to populate it anymore

code sample:

asp:GridView ID="GridView1" runat="server">
    <Columns>
    <asp:TemplateField>
    <ItemTemplate>
      <asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="3" OnDataBound="CheckBoxList1_DataBound" />
    </ItemTemplate>
    </asp:TemplateField>
    </Columns>
    </asp:GridView>

EDIT3:

My code aspx.cs

  public partial class ManyToMany_EditField :  System.Web.DynamicData.FieldTemplateUserControl
  {

 public void Page_Load(object sender, EventArgs e)

   {
    // Register for the DataSource's updating event
    EntityDataSource ds = (EntityDataSource)this.FindDataSourceControl();

    // This field template is used both for Editing and Inserting
    ds.Updating += new EventHandler<EntityDataSourceChangingEventArgs>(DataSource_UpdatingOrInserting);
    ds.Inserting += new EventHandler<EntityDataSourceChangingEventArgs>(DataSource_UpdatingOrInserting);


}

private void DataSource_UpdatingOrInserting(object sender, EntityDataSourceChangingEventArgs e)
{
    MetaTable childTable = ChildrenColumn.ChildTable;

    // Comments assume employee/territory for illustration, but the code is generic

    // Get the collection of territories for this employee
    RelatedEnd entityCollection = (RelatedEnd)Column.EntityTypeProperty.GetValue(e.Entity, null);

    // In Edit mode, make sure it's loaded (doesn't make sense in Insert mode)
    if (Mode == DataBoundControlMode.Edit && !entityCollection.IsLoaded)
    {
        entityCollection.Load();
    }

    // Get an IList from it (i.e. the list of territories for the current employee)
    // REVIEW: we should be using EntityCollection directly, but EF doesn't have a
    // non generic type for it. They will add this in vnext
    IList entityList = ((IListSource)entityCollection).GetList();

    // Go through all the territories (not just those for this employee)
    foreach (object childEntity in childTable.GetQuery(e.Context))
    {

        // Check if the employee currently has this territory
        bool isCurrentlyInList = entityList.Contains(childEntity);

        // Find the checkbox for this territory, which gives us the new state
        string pkString = childTable.GetPrimaryKeyString(childEntity);
        ListItem listItem = CheckBoxList1.Items.FindByValue(pkString);
        if (listItem == null)
            continue;

        // If the states differs, make the appropriate add/remove change
        if (listItem.Selected)
        {
            if (!isCurrentlyInList)
                entityList.Add(childEntity);
        }
        else
        {
            if (isCurrentlyInList)
                entityList.Remove(childEntity);
        }
    }
}

protected void CheckBoxList1_DataBound(object sender, EventArgs e)
{
    MetaTable childTable = ChildrenColumn.ChildTable;
    var a = childTable.CreateContext();
    var dataSource = childTable.GetQuery().AsQueryable();
    var Context = new testEntities();
    var daZtaSource = Context.GetType();

    GridView1.DataSource = dataSource;

    // Comments assume employee/territory for illustration, but the code is generic

    IList entityList = null;
    ObjectContext objectContext = null;

    if (Mode == DataBoundControlMode.Edit)
    {
        object entity;
        ICustomTypeDescriptor rowDescriptor = Row as ICustomTypeDescriptor;
        if (rowDescriptor != null)
        {
            // Get the real entity from the wrapper
            entity = rowDescriptor.GetPropertyOwner(null);
        }
        else
        {
            entity = Row;
        }

        // Get the collection of territories for this employee and make sure it's loaded
        RelatedEnd entityCollection = Column.EntityTypeProperty.GetValue(entity, null) as RelatedEnd;
        if (entityCollection == null)
        {
            throw new InvalidOperationException(String.Format("The ManyToMany template does not support the collection type of the '{0}' column on the '{1}' table.", Column.Name, Table.Name));
        }
        if (!entityCollection.IsLoaded)
        {
            entityCollection.Load();
        }

        // Get an IList from it (i.e. the list of territories for the current employee)
        // REVIEW: we should be using EntityCollection directly, but EF doesn't have a
        // non generic type for it. They will add this in vnext

        entityList =((IListSource)entityCollection).GetList();


        // Get the current ObjectContext
        // REVIEW: this is quite a dirty way of doing this. Look for better alternative
        ObjectQuery objectQuery = (ObjectQuery)entityCollection.GetType().GetMethod(
            "CreateSourceQuery").Invoke(entityCollection, null);
        objectContext = objectQuery.Context;
    }

    // Go through all the territories (not just those for this employee)
   foreach (object childEntity in childTable.GetQuery(objectContext))
    {
        MetaTable actualTable = MetaTable.GetTable(childEntity.GetType());
        // Create a checkbox for it
        ListItem listItem = new ListItem(
            actualTable.GetDisplayString(childEntity),
            actualTable.GetPrimaryKeyString(childEntity));

        // Make it selected if the current employee has that territory
        if (Mode == DataBoundControlMode.Edit)
        {
            listItem.Selected = entityList.Contains(childEntity);
        }

        CheckBoxList1.Items.Add(listItem);
    }

}

public override Control DataControl
{
    get
    {
        return CheckBoxList1;
    }
}

}

My code: Aspx

  <%@ Control Language="C#" CodeFile="ManyToMany_Edit.ascx.cs" Inherits="ManyToMany_EditField" %>

<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatColumns="3" OnDataBound="CheckBoxList1_DataBound" />

Solution

  • Why do you want a checkbox list inside a gridview ? I think you may replace your checkboxlist by a checkbox and add a column with the data you want to display.

    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" showheader="false" allowpaging="true">
        <Columns>
        <asp:TemplateField>
        <ItemTemplate>
          <asp:CheckBox ID="CheckBoxList1" runat="server" checked='<%# Eval("myColumn")%>'/>
        </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="cbxLabel" />
        </Columns>
        </asp:GridView>
    

    You will have the pagination that you are wanting.

    And also don't forget during the page changing to save the checked checkboxes and to restore it also.

    To Paginate your result please take a look at this thread: How to paginate a gridview and SQL custom query with ROW_NUMBER