2

im trying to make a method that creates a List with the name of all the child controls of a DetalsView that are of type string.

The closest i got was:

            foreach (Control c in dv.Controls)
            {
                if (c is Label)
                {
                    controlsToCheck.Add(c.ID);
                }
            }

            foreach (string s in controlsToCheck)
            {
                Label lbl = (Label)dv.FindControl(s);
                if (lbl.Text == "")
                {
                    lbl.Text = "None";
                    lbl.CssClass = "bold";
                }
            }

However, all this does is iterate once in the first foreach, and then exit (ie. dv.Controls only returns one item). If i use FindControl, i can get to the items, but it means i have to do it for each item.

Any toughts?

Thanks!

Edit: here is my DetailsView (i cut some things out, which where just more controls so it fits on the page):

        <asp:DetailsView DefaultMode="ReadOnly" FieldHeaderStyle-CssClass="dwHeader" CssClass="marginLeftRightBottom10px"
            AutoGenerateDeleteButton="true" AutoGenerateEditButton="true" GridLines="None"
            ID="dvIndividualItem" runat="server" AutoGenerateRows="False" DataSourceID="sqldsSingleItem"
            OnDataBound="dvIndividualItem_DataBound">
            <Fields>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Item Name:</h1>
                        <p>
                            The name of the item.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label runat="server" ID="lblItemName" Text='<%# Bind("itemName") %>'></asp:Label>
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox runat="server" ID="tbItemName"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Item Description:</h1>
                        <p>
                            The description of the item.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label runat="server" ID="lblItemDescription" Text='<%# Bind("itemDescription") %>'></asp:Label>
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox runat="server" ID="tbItemDescription"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Item Image:</h1>
                        <p>
                            The image of the item.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Image runat="server" ID="imgItem" Width="40px" Height="40px" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox ReadOnly="true" runat="server" ID="tbItemImage"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Item Type:</h1>
                        <p>
                            Specifies the item type.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblItemType" Text='<%# Eval("itemType") %>' runat="server" />
                    </ItemTemplate>
                    <%--                            <InsertItemTemplate>
                        <asp:DropDownList AutoPostBack="true" OnSelectedIndexChanged="ddlItemTypes_SelectedIndexChanged"
                            DataTextField="itemType" DataValueField="typeId" DataSourceID="sqldsTier1Category"
                            ID="ddlItemTypes" runat="server">
                        </asp:DropDownList>
                        <asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:myDbConnection%>" ID="sqldsTier1Category"
                            runat="server" SelectCommand="dbo.getItemCategories" SelectCommandType="StoredProcedure">
                        </asp:SqlDataSource>
                    </InsertItemTemplate>--%>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Item SubType:</h1>
                        <p>
                            Specifies the sub-item type.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblSubItemType" Text='<%# Eval("itemSubType") %>' runat="server" />
                    </ItemTemplate>
                    <%--                            <InsertItemTemplate>
                        <asp:DropDownList OnDataBound="ddlItemSubTypes_OnDataBound" AutoPostBack="true" DataTextField="itemSubType"
                            DataValueField="subTypeId" DataSourceID="sqldsTier2Category" ID="ddlItemSubTypes"
                            runat="server">
                        </asp:DropDownList>
                        <asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:myDbConnection%>" ID="sqldsTier2Category"
                            runat="server" SelectCommand="dbo.getItemSubCategories" SelectCommandType="StoredProcedure">
                            <SelectParameters>
                                <asp:ControlParameter ControlID="dwNewItem$ddlItemTypes" Name="typeId" PropertyName="SelectedValue"
                                    DbType="Int16" />
                            </SelectParameters>
                        </asp:SqlDataSource>
                    </InsertItemTemplate>--%>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Item SubSubType:</h1>
                        <p>
                            Specifies the sub-sub-item type.</p>
                        <p>
                            <i>Not always applicable.</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblSubSubItemType" Text='<%# Eval("itemSubSubType") %>' runat="server" />
                    </ItemTemplate>
                    <%--                            <InsertItemTemplate>
                        <asp:DropDownList DataTextField="itemSubSubType" DataValueField="subSubTypeId" DataSourceID="sqldsTier3Category"
                            ID="ddlItemSubSubTypes" runat="server">
                        </asp:DropDownList>
                        <asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:myDbConnection%>" ID="sqldsTier3Category"
                            runat="server" SelectCommand="dbo.getItemSubSubCategories" SelectCommandType="StoredProcedure">
                            <SelectParameters>
                                <asp:ControlParameter ControlID="dwNewItem$ddlItemSubTypes" Name="subTypeId" PropertyName="SelectedValue"
                                    DbType="Int16" />
                            </SelectParameters>
                        </asp:SqlDataSource>
                    </InsertItemTemplate>--%>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Requires Sword Swinger Class?</h1>
                        <p>
                            Specifies whether the item can only be used by the Sword Swinger.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="cbReqSwordSwinger" Text='<%# Bind("requiresSwordSwinger") %>' runat="server" />
                    </ItemTemplate>
                    <%--                            <InsertItemTemplate>
                        <asp:CheckBox runat="server" ID="cbReqSwordSwinder" />
                    </InsertItemTemplate>--%>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Requires Rat Catcher Class?</h1>
                        <p>
                            Specifies whether the item can only be used by the Rat Catcher.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="cbReqRatCatcher" Text='<%# Bind("requiresRatCatcher") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:CheckBox runat="server" ID="cbReqRatCatcher" />
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <h1>
                            Requires Spell Mumbler Class?</h1>
                        <p>
                            Specifies whether the item can only be used by the Spell Mumbler.</p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="cbReqSpellMumbler" Text='<%# Bind("requiresSpellMumbler") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:CheckBox runat="server" ID="cbReqSpellMumbler" />
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderStyle-CssClass="colorBlue dwHeader">
                    <HeaderTemplate>
                        <h1>
                            Strength permanently added:</h1>
                        <p>
                            Specifies the amount of strength the item permanently adds to your character.</p>
                        <p>
                            <i>Only available when the item is set to type "Consumable"</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblPermanentStrength" Text='<%# Bind("permanentStrength") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox Enabled="false" runat="server" ID="tbItemPermanentStr"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderStyle-CssClass="colorBlue dwHeader">
                    <HeaderTemplate>
                        <h1>
                            Agility permanently added:</h1>
                        <p>
                            Specifies the amount of agility the item permanently adds to your character.</p>
                        <p>
                            <i>Only available when the item is set to type "Consumable"</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblPermanentAgility" Text='<%# Bind("permanentAgility") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox Enabled="false" runat="server" ID="tbItemPermanentAgl"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderStyle-CssClass="colorBlue dwHeader">
                    <HeaderTemplate>
                        <h1>
                            Magical Power permanently added:</h1>
                        <p>
                            Specifies the amount of magical power the item permanently adds to your character.</p>
                        <p>
                            <i>Only available when the item is set to type "Consumable"</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblPermanentMagicalPower" Text='<%# Bind("permanentMagicalPower") %>'
                            runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox Enabled="false" runat="server" ID="tbItemPermanentMP"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderStyle-CssClass="colorBlue dwHeader">
                    <HeaderTemplate>
                        <h1>
                            Health Points restored:</h1>
                        <p>
                            Specifies the amount of health points the item restores.</p>
                        <p>
                            <i>Only available when the item is set to type "Consumable"</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblHPRestored" Text='<%# Bind("restoresHealthPoints") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox Enabled="false" runat="server" ID="tbItemRestoresHp"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderStyle-CssClass="colorBlue dwHeader">
                    <HeaderTemplate>
                        <h1>
                            Mana Points restored:</h1>
                        <p>
                            Specifies the amount of mana points the item restores.</p>
                        <p>
                            <i>Only available when the item is set to type "Consumable"</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblManaRestored" Text='<%# Bind("restoresMana") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox Enabled="false" runat="server" ID="tbItemRestoresMana"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderStyle-CssClass="colorBlue dwHeader">
                    <HeaderTemplate>
                        <h1>
                            Health Points permanently added:</h1>
                        <p>
                            Specifies the amount of health points the item permanently adds to your character.</p>
                        <p>
                            <i>Only available when the item is set to type "Consumable"</i></p>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:Label ID="lblPermanentHP" Text='<%# Bind("permanentHealth") %>' runat="server" />
                    </ItemTemplate>
                    <InsertItemTemplate>
                        <asp:TextBox Enabled="false" runat="server" ID="tbItemPermanentHP"></asp:TextBox>
                    </InsertItemTemplate>
                </asp:TemplateField>
            </Fields>
        </asp:DetailsView>
TheGateKeeper
  • 4,420
  • 19
  • 66
  • 101

3 Answers3

10

Try this

    public static IEnumerable<Control> GetAllControls(Control parent)
    {
        foreach (Control control in parent.Controls)
        {
            yield return control;
            foreach (Control descendant in GetAllControls(control))
            {
                yield return descendant;
            }
        }
    }

and call

List<Control> ControlsToCheck = GetAllControls(dv).OfType<Label>().ToList();
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • Hmm... your sounds a little too complicated for me. Iv never used those keywords before. Can you explain why mine doesnt work please? – TheGateKeeper Sep 26 '11 at 12:53
  • @TheGateKeeper the controls in DetailsView are not just at one level. They are nested. To get to all controls, you'll have to use a recursive function until to get the simple controls that don't have any more child controls. – Bala R Sep 26 '11 at 13:02
  • Ah ok, i understand now. Doesnt your method iterate 2 levels only thou? – TheGateKeeper Sep 26 '11 at 13:04
  • @TheGateKeeper nope. it's recursive. It will go multiple nested levels until controls don't have any more nested controls (leaf controls, if you consider the whole structure to be a tree-like) – Bala R Sep 26 '11 at 13:09
  • Thanks, i understand your code now. But why did you use return type IEnumerable instead of ArrayList? And w hat does yield mean? Sorry but im still new, never heard of these things before. – TheGateKeeper Sep 26 '11 at 16:23
  • Thanks for this! Why not check whether each control is the desired type before yielding it though? Then you don't have to iterate through again to filter your collection. I'll post what I mean as an answer because it seems to work. – xr280xr Sep 28 '16 at 21:17
3

I modified Bala R's solution a little. I made it a generic extension method that only yeilds the type of control you are interested in so you don't need to call .OfType<T> as a second step:

public static IEnumerable<T> GetControls<T>(this Control parent) where T : Control
{
    foreach (Control control in parent.Controls)
    {
        if (control is T) yield return control as T;
        foreach (Control descendant in GetControls<T>(control))
        {
            if (descendant is T)
                yield return descendant as T;
        }
    }
}

Used like this:

List<Label> labels = dv.GetControls<Label>().ToList();

or

foreach(Label label in dv.GetControls<Label>())
{
    //do stuff
}
xr280xr
  • 12,621
  • 7
  • 81
  • 125
1

When you are iterating through dv.Controls, it's only showing controls at the first level underneath your DetalsView. You need to iterate through all the child controls, and then their children, etc. if you need to find all the Labels.

The answer by @Bala R. is a great example of this. You can also find some examples on this answer.

Community
  • 1
  • 1
Doozer Blake
  • 7,677
  • 2
  • 29
  • 40
  • Hmmmm, so if i add a control directly to its template, wouldnt that be contained directly by the detailsView? Explain please Ah wait i think i understand, its because Div tags count as controls too right? So you need to iterate throu those too. – TheGateKeeper Sep 26 '11 at 13:00
  • @TheGateKeeper No. A DetailsView creates a Table control, which then contails a collection of rows, which then would contain the the table cells, which then finally contain the controls you're looking for. This is why if you want to loop through the controls within it, you need to do so recursively. – Doozer Blake Sep 26 '11 at 13:16