In Search Of ASP.Net Controls

In Search Of ASP.Net Controls

Posted by on 2004年4月24日

Tips for locating controls with the FindControl method, including finding controls in DataGrid rows, Repeaters, DataGrid headers, and user controls.

The FindControl method of the System.Web.UI.Control class appears simple enough to use. In fact, the MSDN description of the method is one simple sentence:

Searches the current naming container for the specified server control.

The key to using FindControl is to invoke the method on the correct container. As a warm up, let’s say we have the following form inside of an aspx page.

 

<form id="Form1" method="post" runat="server">
  <asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
  <asp:Button id="Button1" runat="server" Text="Button"></asp:Button>
</form>

 

Although we can declare a member variable in our code behind class to reference TextBox1, let’s use the FindControl method in an event handler.

 

private void Button1_Click(object sender, System.EventArgs e)
{
   TextBox b = Page.FindControl("TextBox1") as TextBox;
   if(b != null)
   {
      Response.Write("Found TextBox1 on Button1_Click<br>");
   }         
}

 

The above code will find TextBox1 and write a message into the response stream. But what happens when the TextBox is not a child of the control we query with FindControl? Consider the following form.

 

<form id="Form1" method="post" runat="server">
  <asp:Panel id="Panel1" runat="server" Height="152px">
    Panel
    <asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
    <asp:Button id="Button1" runat="server" Text="Button"></asp:Button>
  </asp:Panel>
</form>

 

In the above form, the parent of TextBox1 is the Panel control Panel1. Let’s use the same event handler we used in the first example and see what happens.

Once again we have easily located the control. For later comparison, let’s view an excerpt of the HTML source the ASP.NET form has given us.

 

<div id="Panel1" style="height:152px;">
  Panel
  <input name="TextBox1" type="text" id="TextBox1" />
  <input type="submit" name="Button1" value="Button" id="Button1" />
</div>

 

In the source above we can see ASP.NET has given the TextBox a client side ID of TextBox1, the same ID we use on the server. This behavior changes when we place the textbox inside of a control implementing the INamingContainer interface, which will change the way we use the FindControl method. Any control implementing INamingContainer will create a new control namespace so that all child controls will have a unique ID on the page. In short, an INamingContainer control will guarantee there are no naming conflicts on a page. This behavior is best demonstrated with an example.

FindControl in a DataGrid

There are several ASP.NET controls which implement INamingContainer, including the DataGrid, the Repeater, and the DataList. Let’s build a form with a DataGrid and view the HTML output.

 

<form id="Form1" method="post" runat="server">
   <asp:DataGrid id=DataGrid1 runat="server" DataSource="<%# employees1 %>" 
        AutoGenerateColumns="False"
        OnSelectedIndexChanged="DataGrid1_SelectedIndexChanged"
        OnEditCommand="DataGrid1_EditCommand">
     <Columns>
       <asp:BoundColumn DataField="emp_id" SortExpression="emp_id" HeaderText="emp_id"/>
       <asp:BoundColumn DataField="fname" SortExpression="fname" HeaderText="fname"/>
       <asp:BoundColumn DataField="lname" SortExpression="lname" HeaderText="lname"/>
       <asp:TemplateColumn>
         <ItemTemplate> 
           <asp:TextBox Runat="server" ID="TextBox1" />
         </ItemTemplate>
       </asp:TemplateColumn>
       <asp:ButtonColumn Text="Select" CommandName="Select"></asp:ButtonColumn>
       <asp:EditCommandColumn ButtonType="LinkButton" UpdateText="Update" 
               CancelText="Cancel" EditText="Edit">
       </asp:EditCommandColumn>
     </Columns>
   </asp:DataGrid>
</form>

 

The DataGrid in the form will display data from a well known SQL Server table. Using a TemplateColumn, we will add a TextBox control with the ID of TextBox1 to each row of the grid. Let’s take a look at an excerpt of the HTML ASP.NET generates.

 

<table cellspacing="0" rules="all" border="1" id="DataGrid1">
    <tr>
    <td>emp_id</td><td>fname</td><td>lname</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
  </tr>
  <tr>
    <td>A-C71970F</td><td>Aria</td><td>Cruz</td><td>
      <input name="DataGrid1:_ctl2:TextBox1" type="text" id="DataGrid1__ctl2_TextBox1" />
    </td><td>
  </tr>
  <tr>
    <td>A-R89858F</td><td>Annette</td><td>Roulet</td><td>
      <input name="DataGrid1:_ctl3:TextBox1" type="text" id="DataGrid1__ctl3_TextBox1" />
    </td><td>
  </tr>

 

Here we can see there are many instances of TextBox1, but each ID is prefixed with some additional identifier information. This behavior shows the INamingContainer objects at work. The DataGrid implements INamingContainer and will preface each child control ID with ‘DataGrid1’. As we will see shortly, a DataGrid uses a collection of DataGridItem controls to represent each row of data. A DataGridItem control also implements INamingContainer, and will preface the name of child controls with a it’s own generated identifier (‘_ctrl2’, ‘_ctrl3’, etc.).

Now, if we used the following code, FindControl will return a null value

 

Control c = Page.FindControl(“TextBox1”)

 

The Page control cannot find a TextBox1 because the TextBox controls hide themselves inside of INamingContainer controls. Besides, which control would we really expect FindControl to return? The first TextBox control of the page? The last TextBox control? Typically, when you want to find a TextBox inside of a DataGrid, you’ll be looking for a TextBox on a specific row the user has chosen. For example, we added a Select column to allow the user to click on a hyperlink to chose the selected row. Let’s try to grab the TextBox control in the SelectedIndexChanged event.

 

private void DataGrid1_SelectedIndexChanged(object sender, System.EventArgs e)
{
   TextBox b;
   b = DataGrid1.Items[DataGrid1.SelectedIndex].FindControl("TextBox1") as TextBox;
   if(b != null)
   {
      Response.Write("Sender = " + sender.GetType().ToString() + "<br>");
      Response.Write("Found Textbox1 in SelectedIndexChanged event<br>");
      Response.Write(FindUtil.DumpParent(b));
   }
}

 

The code invokes FindControl on the selected DataGridItem object. The code above will work, as demonstrated in the following figure.

We have also added some additional output to clearly see the chain of ownership leading to our TextBox. The TextBox1 control has a TableCell object as a parent, which in turn is a child control of a DataGridItem object, and so on up the line until we reach a Page control. The code to produce this dump is next.

 

public class FindUtil
{
   public static string DumpParents(Control c)
   {
      StringBuilder sb = new StringBuilder();
      sb.Append(c.ID + " (" + c.GetType().ToString() + ")");

      while(c.Parent != null)
      {
         c = c.Parent;
         sb.Append(" -><br>");
         sb.Append(c.ID + " (" + c.GetType().ToString() + ")");
      }

      return sb.ToString();
   }
}

 

The code will walk up the Parent control references building a string of control IDs (when a control ID exists – not all controls in a form will have a server side ID), and the control type.

We also added an EditCommandColumn to our DataGrid for the user to select a row to edit. Working with the EditCommand event handler is slightly easier, because the second parameter to the handler is of type DataGridCommandEventArgs, which contains a reference to the DataGridItem the user has selected for interaction.

 

protected void DataGrid1_EditCommand(object source, 
                                     DataGridCommandEventArgs e)
{
   TextBox b;
   b = e.Item.FindControl("TextBox1") as TextBox;
   if(b != null)
   {
      Response.Write("Found Textbox1 in EditCommand event<br>");
   }        
}

 

Finding Controls In Headers and Footers

For some DataGrid objects you may want to display an interactive control inside of the header or footer section. These cases require a slightly different method of attack with FindControl. Consider the following form

 

<asp:DataGrid id=DataGrid1 runat="server" DataSource="<%# employees1 %>"
       AutoGenerateColumns="False" ShowFooter="True">
  <Columns> 
    <asp:BoundColumn DataField="emp_id" SortExpression="emp_id" HeaderText="emp_id"/>
    <asp:BoundColumn DataField="fname" SortExpression="fname" HeaderText="fname"/>
    <asp:BoundColumn DataField="lname" SortExpression="lname" HeaderText="lname"/>
    <asp:TemplateColumn>
      <HeaderTemplate>
        <asp:DropDownList Runat="server" ID="DropDownList1">
          <asp:ListItem Value="1">One</asp:ListItem>
          <asp:ListItem Value="2">Two</asp:ListItem>
          <asp:ListItem Value="3">Three</asp:ListItem>
        </asp:DropDownList>
      </HeaderTemplate>
      <ItemTemplate>
        <asp:TextBox Runat="server" ID="TextBox1" />
      </ItemTemplate>
      <FooterTemplate>
        <asp:DropDownList Runat="server" ID="Dropdownlist1">
          <asp:ListItem Value="1">One</asp:ListItem>
          <asp:ListItem Value="2">Two</asp:ListItem>
          <asp:ListItem Value="3">Three</asp:ListItem>
        </asp:DropDownList>
      </FooterTemplate>
    </asp:TemplateColumn>
    <asp:ButtonColumn Text="Select" CommandName="Select"></asp:ButtonColumn>
  </Columns>
</asp:DataGrid>

 

Here we have added a DropDownList control into the HeaderTemplate and FooterTemplate of the DataGrid. We should know at this point we cannot call FindControl on the Page, or on the DataGrid to retrieve these controls, because they will exist inside of another INamingContainer control, specifically a DataGridItem. What might be suprising however, is how we cannot use the DataGrid object’s Items collection as we did earlier. MSDN documentation has the following to say about the Items collection.

Note: Only items bound to the data source are contained in the Items collection. The header, footer, and separator are not included in the collection.

So we will not find the header and footer DataGridItem controls inside the Items collection, but all child controls must exist inside the Controls collection. In this case, our earlier dump of the DataGrid control hierarchy will prove useful. We know the parent of each DataGridItem is a DataGridTable, and the parent of the DataGridTable is the DataGrid control itself. We will have to assume the DataGridTable is the first control in the DataGrid, and the header row will be the first control of the DataGridTable (consequently the footer is the last control of the DataGridTable). Thus the following code:

 

private void DataGrid1_SelectedIndexChanged(object sender, System.EventArgs e)
{
   DropDownList d;                 
   d = DataGrid1.Controls[0].Controls[0].FindControl("DropDownList1") as DropDownList;
   if(d != null)
   {
      Response.Write("Found header DropDownList1 in SelectedIndexChanged event<br>");
   }

   int footerIndex = DataGrid1.Controls[0].Controls.Count-1;
   d = DataGrid1.Controls[0].Controls[footerIndex].FindControl("DropDownList1") as DropDownList;
   if(d != null)
   {
      Response.Write("Found footer DropDownList1 in SelectedIndexChanged event<br>");
      Response.Write(FindUtil.DumpParents(d));
   }
}

 

will give us both DropDownList controls in the header and footer, and produce the following output.

Seeing hard coded index values into the Controls collection is a bit worrisome. If your control changes, or the DataGrid control changes in a newer version of the framework, this code could break. An alternate solution could involve looping through the DataGridTable controls looking for DataGridItem objects with a ItemType property equal to ListItem.Header or ListItem.Footer. Whichever you decide, neither feels extremely robust in the face of future changes.

FindControl in Repeater controls

Like the DataGrid, the Repeater is an INamingContainer. Let’s take a look at the following form which displays authors from SQL Server.

 

<asp:Repeater id="Repeater1" runat="server">
  <ItemTemplate>
     <tr>
        <td><%#DataBinder.Eval(Container.DataItem, "au_id")%></td>
        <td><%#DataBinder.Eval(Container.DataItem, "au_lname")%></td>
        <td><%#DataBinder.Eval(Container.DataItem, "au_fname")%></td>
        <td><asp:TextBox Runat="server" ID="TextBox1" /></td>
        <td><asp:Button Runat="server" ID="Button1" OnClick="Button1_Click" Text="Click" /></td>
     </tr>
  </ItemTemplate>
</asp:Repeater>

 

Each row of the repeater will contain a TextBox and Button control. Every Button control will use the same event handler where we can grab the corresponding TextBox control in the row with the following code.

 

protected void Button1_Click(object sender, System.EventArgs e)
{
   Button btn = sender as Button;
   TextBox tb = btn.Parent.FindControl("TextBox1") as TextBox;
   if(tb != null)
   {
      Response.Write("Found TextBox1 in Button1_Click event<br>");
      Response.Write(FindUtil.DumpParents(tb));
   }
}

 

Here you can see we have taken a different tack by asking for the parent of the Button control which has fired the event handler. In the following screen shot, you can see the parent of the TextBox (and the Button) is a RepeaterItem control (which also implements INamingContainer). Thus the first TextBox appearing on the screen will have an unique ID of Repeater1:_ctl0:TextBox1.

One more tip before we move to the last section. Suppose we added a second button at the bottom of the form with the repeater. When the user clicks this button we want to loop the repeater collecting the contents of each TextBox control from every row. You can accomplish this task with the following code.

 

private void Button2_Click(object sender, System.EventArgs e)
{
   foreach(RepeaterItem item in Repeater1.Items)
   {
      TextBox b = item.FindControl("TextBox1") as TextBox;
      Response.Write(b.Text + "<br>");                       
   }
}

 

User Controls

For the sake of completeness, let’s take a look at how FindControl works when a User Control (ascx) appears. Let’s through the following user control into a form.

 

<%@ Control Language="c#" 
  AutoEventWireup="false" 
  Codebehind="MyUserControl.ascx.cs" 
  Inherits="aspnet.FindControls.MyUserControl" 
  TargetSchema="http://schemas.microsoft.com/intellisense/ie5"
%>

<asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
<asp:Button id="Button1" runat="server" Text="Button"></asp:Button>

 

If we view the HTML output, we will see the following.

 

   <input name="MyUserControl1:TextBox1" type="text" id="MyUserControl1_TextBox1" />
   <input type="submit" name="MyUserControl1:Button1" value="Button" id="MyUserControl1_Button1" />

 

Although user controls do not implement INamingContainer, they do ensure their child controls will not have a naming conflict. For instance, if we placed two of these user controls on the same form, without munging the names we would have two TextBox1 controls on the same form.

Although you generally will not need to do this, you can find a control from the code behind of a user control as easily as the first example in this article

 

private void Button1_Click(object sender, System.EventArgs e)
{
   TextBox b = this.FindControl("TextBox1") as TextBox;
   if(b != null)
   {
      Response.Write("Found TextBox1 on User Control Button1_Click<br>");
   }               
}

 

If you wanted to find the TextBox control from inside of the parent page (not recommended, but here for completeness), you would have to invoke FindControl on the user control. In the following example, we will also use FindControl to find our user control.

 

private void Page_Load(object sender, System.EventArgs e)
{
   MyUserControl u = FindControl("MyUserControl1") as MyUserControl;
   TextBox b = u.FindControl("TextBox1") as TextBox;
   if(b != null)
   {
      Response.Write("Found TextBox1 on Page_Load<br>");
   }         			
}

 

Conclusion

Hopefully this article has shed some light and will offer some assistance to those readers who have lost wayward controls. The behavior of FindControl makes perfect sense once you understand the purpose of INamingContainer and begin using FindControl on the correct objects.

-- by K. Scott Allen


Comments:

A well written article. Thanks.
By SomeNewKid on 2004-6-7
This article answers a very common question on the ASP.NET Forums. It means I can be lazy and point posters to this article.

Thanks!

 

Printing
By db7728 on 2004-6-8
Anyone know how to print this? Thanks!

 

Printing
By scott on 2004-6-11
I'm sorry but we do not have a print friendly format at this time. If you send your email address to admin@odetocode.com I will email the word document to you.

 

Issues with Repeaters or DataList with Seperator Items
By santanaf on 2004-6-14
Keep in mind that with respect to DataList and Repeaters (and perhaps other items) if you include an Item Separator template your controls will not be found as expected. This may be a bug with the .NET framework 1.0 and may be fixed in 1.1, however this is what I found.

Create a DataList with your ItemTemplate, also create a SeparatorTemplate item as well. Place a control in your ItemTemplate and then bind a DataTable to your DataList. Once bound loop over your DataList items using a for loop with an upper bound of DataList.Items.Count. Within the for loop use the null check to determine if DataList.Items[i].FindControl("ControlName") actually finds all of the controls that you may expect it to. It seems to me that the Seperator items are included in the Items Collection of the DataList, however they are not included in the DataList.Items.Count property. There is also no good way that I saw in my brief look to determine if the item you are looking at is a ItemTemplate or a Seperator template. Maybe with the NamingContainer? Perhaps someone can shed some light on this strange behavior for me (or perhaps I am just completely off the rocker with it).

Alex

 

Re: SeparatorTemplate
By scott on 2004-6-14
Hi Alex:

I added a line to the Repeater example:
<SeparatorTemplate><tr><td>blah</td></tr></SeparatorTemplate>

I can still loop through Repeater1.Items without hitting any of the Separator controls in ASP.NET 1.1. Perhaps you could post or email some code that reproduces the problem you found and I could take a look?

 

please reply me soon
By mahsa on 2004-7-9
Hi I try to have just one check box in the footer of datalist and access to that to see if it checked or not I use this sample for datagrid its useful in datalist too
but my problem is I dont want to repeat the check box in each row so I dont want to use the footertemplate in ItemTemplate so now how can I find the check box and hire CheckedChanged event?
<asp:DataList id="DataList1" runat="server">
<ItemTemplate>
1
<asp:CheckBox Visible="False" ID="cbCalculate" Runat="server" AutoPostBack="True"></asp:CheckBox>

<asp:LinkButton Visible="False" ID="lb" Runat="server">uu</asp:LinkButton>
</ItemTemplate>

<FooterTemplate>
<asp:CheckBox ID="Ch_LiftGround" Runat="server" Text="Lift Ground Service" class='caption' AutoPostBack=true></asp:CheckBox>
</FooterTemplate>
</asp:DataList>

Regards...Mahsa

 

How can I find a datagrid embebed into a two datalists?
By carolina_cgu on 2004-10-6
(My english is not very good)
Hi I have a datalist that has another datalist. The second datalist i can find it and i can call it. And I have another datagrid into this datalist. But this datagrid i cant find it.
I use :
CType(sender, DataList).SelectedIndex = E.Item.ItemIndex

Dim dltItem As DataList = Me.dltSucursales.Items(E.Item.ItemIndex).FindControl("dtlAreas")

Anybody can help me?

 

Problem with FindControl in a Repeater
By senyl on 2004-10-8
I found that when you have a repeater with either a HeaderTemplate and/or Footer Template, findcontrol doesn't work too well. I have a repeater bound to a dataview. On OnItemBound, I loop through all the items just as listed in the article. However, for the life of me, findcontrol comes up empty if you utilize a header or footer template. Your choice then is either to do the findcontrol yourself with multiple loops, or don't use a header or footer template, and pull those out of the repeater. If you do the latter, you have to make sure all of the tables are formatted properly. Really a big pain in the rear! If you can do this properly, please tell me how.

 

looping through controls in a repeater
By wilkins on 2004-12-2
I have 2 label controls in the headertemplate section of my repeater. Now at run-time I'm trying to set the text property depending on the users language. How do you do that? I've pasted in my repeater (headertemplate only) code below. I'm able to do this with a label outside the repeater just fine.

thanks.

asp:repeater id="rpPlantTransit" runat="server"> <HeaderTemplate> <table class="DataGrid"> <tr>
<td class="DataGridHeader" width="200px">
<asp:Label ID="lblPlantHeader" Runat="server"></asp:Label>
</td>
<td class="DataGridHeader" width="200px">
<asp:Label ID="lblTransit" Runat="server"></asp:Label>
</td>
</tr> </HeaderTemplate>

... </asp:repeater>

 

Finding Controls In Headers and Footers
By soli on 2004-12-24
How to find controls in Language="VB"

 

How to call Nested Controls
By jmhmaine on 2005-1-20
I have a CheckBoxList control nested in a DataList <selectedItemTemplate>. The data source is from SQL Server tables, so the boxes are built dynamically.

As you can see I have tried using me.FindControl("chblEmailSignup") which works fine when it by itself, but will not work when it is nested in the DataList. Also, I am not able to keep the state of the boxes, so if the user clicks a checkbox and submits the form, the check goes back to unchecked. This might have something to do with it.

Here is the ASPX page:

<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="simpleData.aspx.vb" Inherits="simpleData" Trace="True" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>simpleData</title>
</head>
<body>
<form id="Form1" method="post" runat="server">
<asp:DataList ID="dlEmail_Parent"
Runat="server"
RepeatLayout="Flow"
DataKeyField="FamilyID"
OnItemCommand="DoItemSelect"
OnCancelCommand="DoItemCancel"
EnableViewState="True">
<ItemTemplate>
<asp:ImageButton CommandName="Select"
ImageUrl='/images/page_elements/uparrow.gif' Height="10" Width="11"
runat="server" ID="Imagebutton1" EnableViewState=False />
<%# DataBinder.Eval(Container.DataItem, "FamilyName") %><br>
</ItemTemplate>
<SelectedItemTemplate>
<asp:ImageButton CommandName="Cancel"
ImageUrl='/images/page_elements/downarrow.gif' Height="10" Width="11"
runat="server" ID="Imagebutton2" EnableViewState=False />
<%# DataBinder.Eval(Container.DataItem, "FamilyName") %><br>
<asp:CheckBoxList id="chblEmailSignup"
DataSource='<%# GetChildRelation(Container.DataItem,
"PROJECT_FAMILY_PROJECT") %>'
DataMember='PROJECT'
DataTextField='ProjectName'
DataValueField='ProjectID'
EnableViewState="True"
OnSelectedIndexChanged="Check_Clicked"
Runat="server">
</asp:CheckBoxList>
<asp:Button ID="submitSelections" Text="Submit Selections" Runat="server"
EnableViewState=False />
</SelectedItemTemplate>
</asp:DataList>
<br />
<asp:Literal ID="ltrEmailSignup" Runat="server"
EnableViewState=False />

</form>

</body>
</html>


Here is the VB Code Behind:

Imports System.Data.SqlClient

Public Class simpleData
Inherits System.Web.UI.Page

Protected WithEvents dlEmail_Parent As DataList
Protected WithEvents ltrEmailSignup As Literal

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()

End Sub

'NOTE: The following placeholder declaration is required by the Web
Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
If Not (IsPostBack) Then
bindData()
End If

End Sub


Sub Check_Clicked(ByVal sender As Object, ByVal e As System.EventArgs)
'ltrEmailSignup.Text = "Selected Item(s):<br><br>" &
chblEmailSignup.ClientID

' Iterate through the Items collection of the CheckBoxList
' control and display the selected items.
Dim selectedCBL As CheckBoxList =
CType(Me.FindControl("chblEmailSignup"), CheckBoxList)

Dim i As Integer

If (Not selectedCBL Is Nothing) Then
For i = 0 To selectedCBL.Items.Count - 1
If selectedCBL.Items(i).Selected Then
ltrEmailSignup.Text &= selectedCBL.Items(i).Text &
"<br>"
End If
Next
Else
ltrEmailSignup.Text = "control is equal to nothing" ' I AM
STUCK HERE!!!!
End If


End Sub


Sub bindData()
Dim sqlParent As String = "SELECT FamilyID,FamilyName FROM
PROJECT_FAMILY;"
Dim sqlChild As String = "SELECT ProjectID, ProjectName,
FamilyID FROM PROJECT;"
Dim ds As New DataSet
Dim conn As New SqlConnection

conn.ConnectionString = Global.ConnectionString

'Two commands for two tables
Dim cmdParent As SqlCommand
Dim cmdChild As SqlCommand

'Two datapaters to fill the dataset from two tables
Dim adpParent As SqlDataAdapter
Dim adpChild As SqlDataAdapter


'This handles the relationship between the two columns
Dim datarelation As datarelation
Dim dcParent As DataColumn
Dim dcChild As DataColumn

'First command for first table
cmdParent = New SqlCommand
cmdParent.Connection = conn
cmdParent.CommandText = sqlParent

'Second command for Second table
cmdChild = New SqlCommand
cmdChild.Connection = conn
cmdChild.CommandText = sqlChild

'Now , we will fill the first table and add it to the dataset
adpParent = New SqlDataAdapter
adpParent.SelectCommand = cmdParent
adpParent.TableMappings.Add("Table", "PROJECT_FAMILY")
adpParent.Fill(ds)


'As we did in the previous step , here for the Second table
adpChild = New SqlDataAdapter
adpChild.SelectCommand = cmdChild
adpChild.TableMappings.Add("Table", "PROJECT")
adpChild.Fill(ds)

dcParent = ds.Tables("PROJECT_FAMILY").Columns("FamilyID")
dcChild = ds.Tables("PROJECT").Columns("FamilyID")

'Here we combined two datacolumns to the relations obj
datarelation = New datarelation("PROJECT_FAMILY_PROJECT",
dcParent, dcChild)
ds.Relations.Add(datarelation)

dlEmail_Parent.DataSource = ds.Tables("PROJECT_FAMILY")
dlEmail_Parent.DataBind()


adpParent.Dispose()
adpParent = Nothing
adpChild.Dispose()
adpChild = Nothing
ds.Dispose()
ds = Nothing
conn.Close()
conn = Nothing
End Sub

Function GetChildRelation(ByVal dataItem As Object, ByVal relation
As String) As DataView
'TODO: Test for Null DataItem
Dim drv As DataRowView = CType(dataItem, DataRowView)
Return drv.CreateChildView(relation)
End Function


'====================================================================================
'Sub DoItemSelect(ByVal objSource As Object, ByVal objArgs As
DataListCommandEventArgs)
'
'Handles the event of the Item Select Command from web page

'====================================================================================
Sub DoItemSelect(ByVal objSource As Object, ByVal objArgs As
DataListCommandEventArgs)

dlEmail_Parent.SelectedIndex = objArgs.Item.ItemIndex 'Set the
Seleted Item

bindData()
End Sub


'====================================================================================
'Sub DoItemCancel(ByVal objSource As Object, ByVal objArgs As
DataListCommandEventArgs)
'
'Handles the event of the Item Cancel Command from web page

'====================================================================================
Sub DoItemCancel(ByVal objSource As Object, ByVal objArgs As
DataListCommandEventArgs)
dlEmail_Parent.SelectedIndex = -1 'Leave Select Mode
bindData()
End Sub

End Class

 

Update on Nested CheckBox issue
By jmhmaine on 2005-1-20
I have had partial success, I found a great article on FindControl:
http://www.odetocode.com/Articles/116.aspx

So I changed my original code from
Dim selectedCBL As CheckBoxList = CType(Me.FindControl("chblEmailSignup"), CheckBoxList)

To:

Dim selectedCBL As CheckBoxList = CType(dlEmail_Parent.Items(dlEmail_Parent.SelectedIndex).FindControl("chblEmailSignup"), CheckBoxList)

I'm still having a problem keeping the checkboxes checked between submits. I believe this is also affecting my ASP:Literal control because the value when another item is selected.

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ASP.NETASP.NET Core是两个不同的Web应用程序框架。ASP.NET是Microsoft开发的一种Web应用程序框架,而ASP.NET Core是ASP.NET的下一代版本。 ASP.NET是基于.NET Framework的,而ASP.NET Core是跨平台的,可以在Windows、Linux和macOS上运行。ASP.NET Core还具有更快的性能、更好的可扩展性和更好的安全性。 ASP.NET Core还提供了一种新的开发模型,即基于中间件的管道模型,这使得开发人员可以更轻松地构建和配置Web应用程序。此外,ASP.NET Core还提供了一种新的依赖注入系统,使得开发人员可以更轻松地管理应用程序中的依赖关系。 总之,ASP.NETASP.NET Core都是用于构建Web应用程序的框架,但它们之间存在一些重要的区别,包括支持的平台、性能、可扩展性和开发模型等方面。 ### 回答2: ASP.NETASP.NET Core都是Microsoft公司开发的Web应用程序框架,两者之间有很多不同之处。这篇文章将讨论它们之间的这些不同点。 1. 跨平台支持: ASP.NET是运行在Windows操作系统上的Web应用程序框架,而ASP.NET Core则是跨平台的。因此,在MacOS和Linux等其他操作系统上也可以使用ASP.NET Core。 2. 依赖的第三方库: ASP.NET依赖于大量的第三方库和框架,这些库可以添加到项目中以增强其功能。但是ASP.NET Core开发人员更多的将自己的应用程序依赖配置在库中,例如,.NET中的NuGet包。 3. 性能: 相比ASP.NETASP.NET Core更快,更高效。其中一个原因是,ASP.NET Core不需要与IIS(Internet Information Services)进行交互,这意味着更少的资源被分配, 4. 打包: ASP.NETASP.NET Core都可以使用NuGet包管理器来进行打包,但是ASP.NET Core可以将其应用程序打包为单个可执行文件,这使得开发和部署更加容易。 5. 依赖的编程语言: ASP.NET Core只能使用C#和F#等可将代码编译为.NET Core的语言,而ASP.NET则可以使用任何可编译为.NET框架的语言,包括C#,VB.NET和C++。 6. JWT的授权: 在ASP.NET Core中,JSON Web Token(JWT)是第一类公民,而在ASP.NET中,它只能使用第三方库进行实现。 7. MVC: 在ASP.NET Core中,MVC(Model-View-Controller)是默认的Web应用程序架构,但是在ASP.NET中,MVC需要安装一个独立的模板。 8. 版本: ASP.NET Core是最新的Web应用程序框架,而ASP.NET是较旧的。因此,ASP.NET Core提供了更多的功能和性能,而ASP.NET则使用固定的框架版本。 总之,虽然两者都是Microsoft公司开发的Web应用程序框架,但是它们之间还是有很多不同之处。因此,选择使用哪个框架取决于项目的要求,例如,是否需要跨平台支持和性能等。 ### 回答3: ASP.NET是一种Web应用程序框架,由Microsoft公司推出,它是Microsoft .NET运行时环境的一部分。ASP.NET提供了丰富的开发工具和框架,包括Web Forms、MVC、Web API等。它通常与IIS(Internet Information Services)一起使用,作为Web服务器上的应用程序。 ASP.NET Core是一个开源的、跨平台的Web应用程序框架,也是由Microsoft公司推出。它是Architecture Unified(一体化架构)领域的一项重要创新。ASP.NET Core是.NET平台上的一个新的、轻量级Web框架,可以跨平台运行在Windows、macOS和Linux等操作系统上。它同时支持Web Forms、MVC和Web API等多种编程模型,具有高度灵活性和可扩展性。 下面我们来详细看一下ASP.NETASP.NET Core的区别: 1.跨平台性:ASP.NET只能运行在Windows环境下,而ASP.NET Core可以运行在Windows、Linux和macOS等操作系统上。 2.开源性:ASP.NET是Microsoft公司的闭源产品,而ASP.NET Core是一个开源的多平台Web框架,所有代码都进行了公开。 3.轻量级:ASP.NET Core是一个轻量级的框架,文件大小比ASP.NET小很多,启动速度也更快。而ASP.NET则是重量级的框架,需要较高的硬件配置和更长的启动时间。 4.性能:ASP.NET Core的性能比ASP.NET更好,这是因为它是一个基于模块化设计的框架。模块化设计使得ASP.NET Core可以更容易地进行优化和扩展,而且运行时内存的消耗也更小。 5.配置简单:ASP.NET Core的配置更加简单,可以使用依赖注入模式来配置应用程序。而ASP.NET则需要在Web.config中进行大量的配置。 6.兼容性:ASP.NET Core不支持Web Forms的开发模式,而ASP.NET支持Web Forms、MVC和Web API等多种开发模式。 综上所述,ASP.NETASP.NET Core的最大区别在于跨平台性、开源性、轻量级、性能和配置的简单等方面。ASP.NET Core是一个新的、基于模块化设计的Web框架,具有更高的性能、更好的跨平台性和更简单的配置,未来将会成为ASP.NET的主要发展方向。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值