tags:

views:

1096

answers:

7

I am writing a webpage in C# .NET. In javascript there is a function called GetElementsByTagName... this is nice for javascript invoked from the .aspx page. My question is, is there any way I can have this kind of functionality from my C# code-behind?

--

The scenario for those curious: I used an asp:repeater to generate a lot of buttons, and now I'm essentially trying to make a button that clicks them all. I tried storing all the buttons in a list as I created them, but the list is getting cleared during every postback, so I thought I could try the above method.

+1  A: 

FindControl(), or iterate through the controls on the page...

For each ctl as Control in Me.Controls
  If ctl.Name = whatYouWant Then
    do stuff
Next 'ctl

--If you are creating the controls, you should be setting their ID's

Dim ctl as New Control()
ctl.ID = "blah1"

etc...

StingyJack
sorry for the vb. I can translate if needed
StingyJack
FindControl(string) doesn't work because I don't know their id's. The VB makes sense, but I don't know what I would use in C# in leiu of that Me.Controls
Aaron
this.Controls is the C# equiv
Mark Brackett
+1  A: 

Well, you can find controls with the page's FindControl method, but Repeater elements have names generated by .net.

As an aside, if you really want to, you could store the list of buttons in your page's ViewState (or perhaps a list of their names).

Dana
I tried storing a List<Button> in the ViewState, but it got ugly-- the thing crashed, saying it couldn't serialize buttons. List<String> might work tho- I will try that if this doesn't work. Thanks.
Aaron
A: 

Whenever you do any postback, everything is recreated, including your databound controls.

If your list is gone, so are the button controls. Unless, of course, you've recreated them, and in that case you should have recreated the list as well.

Joel Coehoorn
Unfortunately the sequence is like this:-Create Buttons/List-Click New Button that clicks all other button: -This causes a postback, so the screen goes white, and immediately after it tries to expand the buttons... which don't exist.I could be doing it wrong, I dont know.
Aaron
Sounds like your issue is a matter of design.
alord1689
+2  A: 

Try this:

foreach (Control ctl in myRepeater.Controls)
{ 
  if (ctl is Button)
  {
    ((Button)ctl).Click();
  }
}

HTH...

alord1689
your going to miss buttons that are in containers, like panels and stuff with this method. I'd use a recursive function.
stephenbayer
But he said it's in a Repeater. Recursion would be overkill, wouldn't it?
alord1689
A: 

I don't know exactly what you mean by clicks them all. But how would this following code work for you? I don't know, I haven't tested...

protected void Page_Load(object sender, EventArgs e)
{

    foreach (Control control in GetControlsByType(this, typeof(TextBox)))
    { 
        //Do something?
    }

}
public static System.Collections.Generic.List<Control> GetControlsByType(Control ctrl, Type t)
{
    System.Collections.Generic.List<Control> cntrls = new System.Collections.Generic.List<Control>();


    foreach (Control child in ctrl.Controls)
    {
        if (t == child.GetType())
            cntrls.Add(child);
        cntrls.AddRange(GetControlsByType(child, t));
    }
    return cntrls;
}
stephenbayer
better yet, you can add an extension method on Control called GetControlsByType or something allong that line... i actually am liking the extension methods more, they are growing on me.
stephenbayer
A: 

ASPX:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml"&gt;
    <head runat="server">
        <title>Untitled Page</title>
    </head>

    <body>
        <form id="form1" runat="server">
            <asp:Repeater runat="server" ID="Repeater1">
                <ItemTemplate>
                    <asp:Button runat="server" ID="Button1" Text="I was NOT changed" />
                </ItemTemplate>
            </asp:Repeater>
        </form>
    </body>
</html>

ASPX.CS:

using System;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;


public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(Object sender, EventArgs e)
    {
        DataTable dt = new DataTable();

        dt.Columns.Add(new DataColumn("column"));

        DataRow dr = null;

        for (Int32 i = 0; i < 10; i++)
        {
            dr = dt.NewRow();

            dr["column"] = "";

            dt.Rows.Add(dr);
        }

        this.Repeater1.DataSource = dt;
        this.Repeater1.DataBind();


        foreach (RepeaterItem ri in this.Repeater1.Controls)
        {
            foreach (Control c in ri.Controls)
            {
                Button b = new Button();


                try
                {
                    b = (Button)c;
                }

                catch (Exception exc)
                {
                }


                b.Text = "I was found and changed";
            }
        }
    }
}
roosteronacid
That inner loop would be *much* better as:Button b = c as Button;if (b != null) b.Text = "I was found and changed";
Mark Brackett
A: 

Or a variation of my own code, only changing the ASPX.CS:

using System;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;


public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(Object sender, EventArgs e)
    {
        #region Fill Repeater1 with some dummy data
        DataTable dt = new DataTable();

        dt.Columns.Add(new DataColumn("column"));

        DataRow dr = null;

        for (Int32 i = 0; i < 10; i++)
        {
            dr = dt.NewRow();

            dr["column"] = "";

            dt.Rows.Add(dr);
        }

        this.Repeater1.DataSource = dt;
        this.Repeater1.DataBind();
        #endregion


        foreach (Button b in this.FindButtonsInRepeater(ref this.Repeater1))
        {
            b.Text = "I was found and changed";
        }
    }


    private List<Button> FindButtonsInRepeater(ref Repeater repeater)
    {
        List<Button> buttonsFound = new List<Button>();


        foreach (RepeaterItem ri in repeater.Controls)
        {
            foreach (Control c in ri.Controls)
            {
                try
                {
                    buttonsFound.Add((Button)c);
                }

                catch (Exception exc)
                {
                }
            }
        }


        return buttonsFound;
    }
}
roosteronacid
Unless your changing which object that repeater points to, there's no need for a ref parameter.
Mark Brackett