3

I am developing a SharePoint 2010 non-visual WebPart which displays some kind of data in a big table. The table rows should be filtered by selecting a filter criterium from a DropDownList which is part of the webpart.

The OnSelectedIndexChanged event of the DropDownList is fired after CreateChildControls and before OnPreRender. Because the cells of the table contain LinkButtons with an OnClick event attached, they must be created in CreateChildControls in order to get the OnClick events fired.

I don't know which rows of the table to hide until the OnSelectedIndexChanged of the DropDownList is fired, so I create all possible table rows in CreateChldControls and try to remove the filtered ones later in OnSelectedIndexChanged the event directly or in OnPreRender. The rows were physically removed from the parent Table's control collection, but they are nevertheles displayed.

As a test, I tried to remove some random rows at the end of the CreateChildControls method after creating them, it worked and the rows were not rendered.

How I remove the rows:

  Table mt = FindControl("matrixtable") as Table;

  Helpers.Log("Controls in Table: " + mt.Controls.Count);
  foreach (int kdid in kdIdsInvisible)
  {
     TableRow c = mt.FindControl("kdrow" + kdid) as TableRow;
     Helpers.Log(c.ID);
     mt.Controls.Remove(c);
  }
  Helpers.Log("Controls in Table: " + mt.Controls.Count);

Output:

Controls in Table: 88
Controls in Table: 2

But all rows are still rendered...

Is there a solution for this? Thank you in advance!

elsni
  • 1,953
  • 2
  • 17
  • 35
  • Are you sure you are not databinding after your removed the controls? Try to do the remove on PreRender. – Peter Jul 29 '13 at 08:03
  • I tried to remove the controls in OnPreRender first. It did not work. The controls were removed, (I checked that) but they are rendered anyway. Removing the controls only worked in CreateChildControls, but at this time I do not know which to remove. I would know that in OnPreRender. Chicken or egg dilemma. – elsni Jul 29 '13 at 08:20
  • Instead of adding the table on CreateChildControls, add the items to a seperate list. Then add then in OnPreRender where you know which ones to add. Just a workaround. It seens the is something else wrong with your code, and you will have problems with handling the postback event if you do not add the dynamic controls on init or load. Maybe you can store the list in your viewstate to do the correct rendering there. – Peter Jul 29 '13 at 08:31
  • Also tried that. If I add them in OnPreRender, the events are not thrown on postback. I suspect the controls must be added in create child controls, because the event methods are executed betrween CreateChildControls and OnPreRender. – elsni Jul 29 '13 at 08:35
  • To Answer your first question: I do not use databinding at all. – elsni Jul 29 '13 at 08:42

2 Answers2

2

Debugging:

Loop through and write to the screen all the IDs of all the rows of the table.

Then loop through again, and write to the screen all the row IDs that were deleted.

Find the two rows that were not delete, and see if they have an ID at all. There may be a split table cell or something.

Worst case scenario, debug the WP in visual studio and watch the rows deleted one by one and watch the count of the table to see which one's are being skipped. Try deleting those rows for the immediate window, and see what error you get.

detailCode
  • 537
  • 1
  • 8
  • 22
1

I think you need to remove the row from the table rows collection. Try replacing the line mt.Controls.Remove(c); with mt.Rows.Remove(c);

Here is a working example of removing rows in the SelectedIndexChanged event

[ToolboxItemAttribute(false)]
public class TableTest : WebPart
{
    protected override void CreateChildControls()
    {
        // Build a table
        Table t = new Table();
        t.ID = "table";
        for (int i = 0; i < 11; i++)
        {
            TableRow tr = new TableRow();
            t.Rows.Add(tr);
            for (int j = 0; j < 5; j++)
            {
                TableCell tc = new TableCell();
                tc.Controls.Add(new LiteralControl("Row " + i + " Cell " + j));
                tr.Cells.Add(tc);
            }
        }
        // Add a dropdown
        DropDownList dl = new DropDownList();
        dl.AutoPostBack = true;
        dl.Items.Add(new ListItem { Text = "Odd", Value = "1" });
        dl.Items.Add(new ListItem { Text = "Even", Value = "2" });
        dl.SelectedIndexChanged += dl_SelectedIndexChanged;

        // Add to the controls collection
        Controls.Add(dl);
        Controls.Add(t);
    }

    void dl_SelectedIndexChanged(object sender, EventArgs e)
    {
        // Get the table and dropdown
        Table t = FindControl("table") as Table;
        DropDownList dl = sender as DropDownList;
        if (t != null && dl != null)
        {
            int i = 1;
            // Set up a list to hold the rows to remove
            IList<TableRow> removeRows = new List<TableRow>();

            if (dl.SelectedValue == "1") // Get all odd rows
            {                   
                foreach (TableRow tr in t.Rows)
                {
                    if (i % 2 == 0)
                    {
                        removeRows.Add(tr); // Add odd rows to the list of rows to remove
                    }
                    i++;
                }
            }
            else // Get all even rows
            {
                foreach (TableRow tr in t.Rows)
                {
                    if (i % 2 == 1)
                    {
                        removeRows.Add(tr); // Add even rows to the list of rows to remove
                    }
                    i++;
                }
            }

            foreach (var tr in removeRows)
            {
                t.Rows.Remove(tr); // Remove the rows from the table
            }
        }
    }
} 
Aquila Sands
  • 1,471
  • 1
  • 20
  • 28