find all labels in GridViewRow

T

tshad

How do you find all the labels in a GridViewRow?

I tried this:

*********************************************
foreach (GridViewRow gvr in GridView1.Rows)
{
foreach (Control ctrl in gvr.Controls)
{
ctrl.GetType();
}
}
*********************************************

ctrl comes back with:

{Name = "DataControlFieldCell" FullName =
"System.Web.UI.WebControls.DataControlFieldCell"} System.Type
{System.RuntimeType}

How do I tell if this is a Label or not?

What I need to do is change the Background and Foreground colors to some
color.

I would do something like:

((Label)ctrl).BackColor = xxx;
((Label)ctrl).ForeColor = xxx;

or

((Label)ctrl).Attributes.Add("style",
"background-color:purple;foreground-color:yellow");

But I need to figure out how to determine if the control is a Label.

Thanks,

Tom
 
T

tshad

I tried to use the following to test if a Label:

if(ctrl.GetType() == typeof(Label))
e = e;
else
e = e;

But it never equated to a label and I know the rows had labels in them.
Here is a part of my GridView:

********************************************
<asp:GridView ID="GridView1"
AutoGenerateColumns="False"
SkinID="mGridViewSkin"
CssClass="Grid100" Width="500px"
AllowPaging="True"
AllowSorting="True"
PageSize="100"
PagerSettings-Mode="NumericFirstLast"
PagerStyle-CssClass="GridViewPager"
OnPageIndexChanged="mGridView_PageIndexChanged"
OnRowEditing="GridView1_RowEditing"
OnRowDataBound="GridView1_RowDataBound"
OnRowUpdating="GridView1_RowUpdating"
runat="server">
<AlternatingRowStyle CssClass="GridAltItem"/>
<RowStyle CssClass="GridItem" ForeColor="#0000FF"/>
<HeaderStyle CssClass="GridViewHeader" />
<Columns>
<asp:TemplateField HeaderText="ID" HeaderStyle-Width="40px"
Visible="false">
<ItemTemplate>
<asp:Label ID="lblExceptionID" runat="server"
CssClass="GridViewAlternatingRow" Text='<%#
Eval("ExceptionID") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ID2" HeaderStyle-Width="40px"
Visible="false">
<ItemTemplate>
<asp:Label ID="lblDetailID" runat="server"
CssClass="GridViewAlternatingRow" Text='<%#
Eval("DetailID") %>' />
</ItemTemplate>
</asp:TemplateField>

....

********************************************

Tom
 
J

Jesse Houwing

Before I can really answer this, you'll need to learn a bit about how a
ASP.NET page is made up.

Basically the page is a container for controls, and each control can
have one or more childcontrols.

If you look at the grid in question it'll look something like this:

Page
- Grid
- - Row
- - - Cell
- - - - Label
- - - Cell
- - - - Label
- - Row... etc

So if you loop through all the childcontrols of the row, you'll only
find the cells that are directly underneath it. If you want to access
the labels, you'll have to dig even deeper. Depending on what you've
actually put into these cells, you might even have to go much deeper.

The easiest way to solve this is to use recursion (or make it stack
based for optimum performance). Just go through every control and their
child controls and test if you've found a label. Or, if you know the
name of these labels, let ASP.NET do the searching and go from there.

so:

public void SetLabelColor(WebControl control)
{
Label l = control as Label;
if (l != null)
{
l.BackColor = "...";
l.ForeColor = "...";
}
else if (control.HasControls())
{
foreach (WebControl c in control.Controls)
{
SetLabelColor(c);
}
}
}

And just call it like this:

SetLabelColor(GridView1);

Or, based on the name of the label:

foreach(GridViewRow gvr in GridView1.Rows)
{
Label l = gvr.FindControl("LabelID") as Label;
if (l != null)
{
l.BackColor = "...";
l.ForeColor = "...";
}
}



* tshad wrote, On 19-1-2010 22:08:
 
J

Jesse Houwing

* Jesse Houwing wrote, On 19-1-2010 23:16:
The easiest way to solve this is to use recursion (or make it stack
based for optimum performance). Just go through every control and their
child controls and test if you've found a label. Or, if you know the
name of these labels, let ASP.NET do the searching and go from there.

The non-recursive version looks like this:

public void SetLabelColor(WebControl control)
{
Stack<WebControl> todo = new Stack<WebControl>();
todo.Push(control);

while (todo.Count > 0)
{
Label l = todo.Pop() as Label;
if (l != null)
{
l.BackColor = "...";
l.ForeColor = "...";
todo.Pop();
}
else if (control.HasControls())
{
foreach (WebControl c in control.Controls)
{
todo.Push(c);
}
}
}
}
 
T

tshad

If I am going through 500 rows at a crack, which would be more efficient?

The recursive loop or using FindControl (I am dealing with about 12 labels
per row).

Thanks,

Tom
 
T

tshad

How do you tell if the contol is a label?

What is Label1 defined as?

I assume that:

Label l = control as Label;

Will set it to the pointer to the control if the control is a valid Label
and null if not?

Thanks,

Tom
 
P

Peter Duniho

Jesse said:
* Jesse Houwing wrote, On 19-1-2010 23:16:

The non-recursive version looks like this:

public void SetLabelColor(WebControl control)
{
Stack<WebControl> todo = new Stack<WebControl>();

Uh, well…that's not really a non-recursive version. Just because you've
implemented the stack behavior explicitly rather than using the
language-defined one doesn't change the inherent recursiveness of the
algorithm. :p

Regardless, it seems to me you have one too many calls to the Pop()
method in there…did you originally have a Peek() or something? And
you're not handling the case where a Label control has children; I don't
know if that's possible in ASP.NET, but it certainly can happen in Forms
or WPF.

Seems to me that a better/more-correct implicit recursive implementation
would look like this:

public void SetLabelColor(WebControl control)
{
Label l = control as Label;

if (l != null)
{
l.BackColor = "...";
l.ForeColor = "...";
}

foreach (WebControl c in control.Controls)
{
SetLabelColor(c);
}
}

And of course the explicit recursive implementation would be very similar:

public void SetLabelColor(WebControl control)
{
Stack<WebControl> stack = new Stack<WebControl>();

stack.Push(control);

while (stack.Count > 0)
{
control = stack.Pop();

Label l = control as Label;

if (l != null)
{
l.BackColor = "...";
l.ForeColor = "...";
}

foreach (WebControl c in control.Controls)
{
stack.Push(c);
}
}
}

Pete
 
P

Peter Duniho

tshad said:
If I am going through 500 rows at a crack, which would be more efficient?

The recursive loop or using FindControl (I am dealing with about 12 labels
per row).

If you only have one control that needs to be updated, you might as well
use FindControl().

If you have multiple controls that need to be updated based on some
specific criteria, you might as well do the enumeration yourself,
embedding that criteria withing the enumeration.

Or you can be fancy and use a predicate delegate to represent the
criteria, generalizing the enumeration that way…you could also
generalize the actual update too if you like, using an action delegate.
That might look something like this:

void ForEach(WebControl control, Predicate<WebControl> check,
Action<WebControl> apply)
{
if (check(control))
{
apply(control);
}

foreach (WebControl child in control.Controls)
{
ForEach(child, check, apply);
}
}

Then you might use it like this:

ForEach(gridView1, c => c is Label, c =>
{
Label l = (Label)c;

l.BackColor = "...";
l.ForeColor = "...";
});

For extra credit: generalize the above "ForEach()" method so it itself
is generic. Then, get rid of the method altogether, instead using LINQ. :)

Pete
 
J

Jesse Houwing

* Peter Duniho wrote, On 20-1-2010 0:54:
Uh, well…that's not really a non-recursive version. Just because you've
implemented the stack behavior explicitly rather than using the
language-defined one doesn't change the inherent recursiveness of the
algorithm. :p

Agreed. But it doesn't use a recursive method call, which is what I meant.
Regardless, it seems to me you have one too many calls to the Pop()
method in there…did you originally have a Peek() or something?

Hmm indeed. I changed the sample half way and seem to have forgotten to
remove the second pop().
And
you're not handling the case where a Label control has children; I don't
know if that's possible in ASP.NET, but it certainly can happen in Forms
or WPF.

No, a Label in ASP.NEt cannot contain child controls, or at least not
the default Label control. One could hnherit from the default label and
allow for child controls I guess, but I've never seen anyone do that
before. It's not recommended to do so, that's why I ignored the possibility.

Your version would indeed take that into account.
 
T

tshad

Am I doing this wrong?

I changed the capitialization,
foreach(GridView1, c => c is Label, c =>
{
Label l = (Label)c;

l.BackColor = System.Drawing.Color.BlueViolet;
l.ForeColor = System.Drawing.Color.Yellow;
});

but it gives me errors like:

GridView1 is a control. GridView1 is a field but it is being used as a
method.

and

(parameter) ? c

Thanks,

Tom
 
P

Peter Duniho

tshad said:
Am I doing this wrong?

I changed the capitialization,
foreach(GridView1, c => c is Label, c =>
{
Label l = (Label)c;

l.BackColor = System.Drawing.Color.BlueViolet;
l.ForeColor = System.Drawing.Color.Yellow;
});

You can't change the capitalization. "foreach" is a reserved word in C#.
but it gives me errors like:

GridView1 is a control. GridView1 is a field but it is being used as a
method.

and

(parameter) ? c

Diagnosing compiler errors without a complete code example can be
difficult. But if you've literally tried to rename the method I posted
from "ForEach" to "foreach", that's just not going to work.

Pete
 
T

tshad

Nevermind, I was doing it wrong.

I didn't realize that ForEach was a function.

Thanks,

Tom
 
T

tshad

I hadn't realized that ForEach was a function and figured you were using the
C# foreach.

Thanks,

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top