How do I dynamically create, and populate a Table (DataTable?) - asp.net

The Issue I am currently facing is, I would like Keep the HMTL Table Structure I currently have, if at all possible.I would like tp dynamically create this table instead of doing so at the HTML level. I would Like to do so dynamically at the data level. Originally I had created a table via the ASPX page, and then I realized that I would have to go back and dynamically add in new revised row changes. This got ugly really quickly. my plan was to traverse each row in the table until i found the place I wanted to add a new row of data, but then I realized that it would mess up the columns to the right of the data, causing unwanted gaps if I added anything in the first 2 columns. I tried this code originally:
For Each row As HtmlTableRow In tblDates.Rows
For Each col As HtmlTableCell In tblDates.Columns
If col.ID = "lblSubmittedToESO" Then
tblDates.InnerHtml += "<tr> "
tblDates.InnerHtml += "<td> <asp:Label ID='lblSubmittedToESO' runat='server' Text='Date Site Plan Submitted to ESO for Approval: '></asp:Label></td>"
tblDates.InnerHtml += ""
tblDates.InnerHtml += ""
tblDates.InnerHtml += "</tr>"
End If
Next
Next
However, as you already know.. this did not work as there was no such thing as "tblDates.Columns". The original structure of my table is as follows:
<table id="tblDates" runat ="server" border="1">
<tr id ="tblDatesHeader">
<td>
</td>
<td align="center">
<asp:Label ID="lblDate" runat="server" Text="Date" Font-Bold="true"></asp:Label>
<br />
<asp:Label ID="lblDateFormat" runat="server" Text="(MM/DD/YYYY)" Font-Bold="true"></asp:Label>
</td>
<td colspan="2" align="center">
<asp:Label ID="lblNumOfDays" runat="server" Text="Number of Days to Complete Action"
Font-Bold="true"></asp:Label>
</td>
</tr>
<tr id ="ECOSubmitRow">
<td>
<asp:Label ID="lblSubmittedToECO" runat="server" Text="Date Site Plan Submitted to ECO for Approval: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtSubmittedToECO" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblPMO" runat="server" Text="PWO: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtPMO" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="ECOSignedRow">
<td>
<asp:Label ID="lblSignedByECO" runat="server" Text="Date Site Plan Signed by ECO: "></asp:Label> <img src="img/help_bubble.gif" id="helpbubble5" alt="" />
</td>
<td>
<asp:TextBox ID="txtSignedByECO" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblECO" runat="server" Text="ESO: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtECO" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="PMOSubmitRow">
<td>
<asp:Label ID="lblSubmittedToPMO" runat="server" Text="Date Site Plan Submitted to PMO for Approval: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtSubmittedToPMO" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblPMOECO" runat="server" Text="PMO/ECO sign to EED/MSC: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtPMOECO" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="PMOSignedRow">
<td>
<asp:Label ID="lblSignedByPMO" runat="server" Text="Date Site Plan Signed by PMO: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtSignedByPMO" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblEED" runat="server" Text="EED/MSC: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtEED" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="EEDSubmitRow">
<td>
<asp:Label ID="lblSubmittedToEED" runat="server" Text="Date Plan Submitted to EED for Endorsement: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtSubmittedToEED" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblABA" runat="server" Text="ABA: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtABA" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="EEDEndorcedRow">
<td>
<asp:Label ID="lblEndorsedByEED" runat="server" Text="Date Endorsed by EED/MSC and Forwarded to ABA: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtEndorsedByEED" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblOverallCycle" runat="server" Text="Project Overall Cycle Time: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtOverallCycle" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="ActionRow">
<td>
<asp:Label ID="lblABAaction" runat="server" Text="Date of ABA Action (Endorsement/Approval/Return): "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtABAaction" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="InitDateRow">
<td>
<asp:Label ID="lblABAAAIInitDate" runat="server" Text="Inititial Date AAI was Issued: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtInitAAIDate" runat="server"></asp:TextBox>
</td>
</tr>
<tr id ="AAISubmitRow">
<td>
<asp:Label ID="lblAAISubmitted" runat="server" Text="Date Request Information Submitted: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtFIDate" runat="server"></asp:TextBox>
</td>
<td>
<asp:Label ID="lblFIDays" runat="server" Text="RFI Overall Days: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtRFITotal" runat="server"></asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
<tr align="center">
<td colspan="2">
<asp:Label ID="lblRating" runat="server" Text="Rating (see note):" Font-Bold="true"></asp:Label>
</td>
<td>
<asp:Label ID="lblEEDEval" runat="server" Text="FEC or MCSC<br>Evaluation<br>Score: 0-100"
Font-Bold="true" Width="200px"></asp:Label>
</td>
<td>
<asp:Label ID="lblSSAEval" runat="server" Text="SSA<br>Evaluation<br>Score: 0-100"
Font-Bold="true"></asp:Label>
</td>
</tr>
<tr align="center">
<td colspan="2">
<asp:Label ID="lblOverall" runat="server" Text="Overall Score From Evaluation on Next Page:"></asp:Label>
</td>
<td align="center">
<asp:TextBox ID="txtFECOverall" runat="server" Width="40px"></asp:TextBox>
</td>
<td align="center">
<asp:TextBox ID="txtNossaOverall" runat="server" Width="40px"></asp:TextBox>
</td>
</tr>
</table>
So right now I have 4 stored procedures that pull dates for 4 different process. what I would like to is dynamically create this table and add the dates that I have already pulled and stored into objects and place them in this table in their specific position. Originally once I pulled the date I just added them in by referencing the "ID" of the . Normally it would be just adding a datasource and populating the table with that once source, but I would also like to design the layout. Attached to this question is a link for image to show what it looks like when I orginally created it. However, Now I would like to build it dynamically. Sample Table Output of Table Originally
Is there away to design the table this way, layout-wise?

Well, the issue (and difficult challenge) is that you thinking of a table in HTML and markup on the page. The problem is that 'table' as HTML is just markup, and as a result, REALLY difficult to work with.
So, what you want to do is at a conceptial level split out (seperate) your UI display of the table, and the the actual table you create in code.
So, think of the problem this way:
code + a table in memory.
HTML markup - display of the table.
So, once we split the two concepts?
Well, now you create that table, add rows to that table, maybe loop and sum a column on that table.
AND THEN display + render the results of that table.
Note the separation here. We have a data table. We do whatever we want with that table, AND THEN RENDER the table in HTML.
Note how we thus don't try to loop, try to modify, try to change the HTML table. (its too painful).
The other bonus? Well, in most cases we can assume you have a database. Thus, once again, the concept of the data, the data operations are 100% separate from what we going to display to the UI.
So, think data table operations. Do whatever.
THEN we render + display that table.
The above also means then we can use one of the "many" data repeating controls to do all the heavy lifting of the "display", but the code never really hits, touches, and attempts to modify the HTML - we only "render" the data AFTER we done our data operations.
if you break the above concept (data operations, and HMTL UI operations), then you have to start writing boatloads of code to try and update the HTML, but worse, the HTML is ONLY a representation of that internal data table anyway.
So, MUCH less work to do data operations, and when done, then just have asp.net do this:
Mr. asp.net, can you now just display my table for me? (especially after I done my data operations).
Since asp.net net can render + display that data table, and do so without looping or me having to write that code, then that's the approach I recommend.
my plan was to traverse each row in the table until i found the place I wanted to add a new row of data,
Caution!!!! - you don't really have a "place" in your data. You add a row of data to the system, and then query or pull or sort the data in the order you want. Data operations as a general rule does NOT have a order. You might have some invoice number, or some other column that you can (or want to) sort on, but again, thinking of data like old style punched cards in which order matters is a LESS then ideal way to think of data.
Your data is a bucket of rows. You do operations against that data, and THEN send it to the browser to be rendered as a table. Again, note the concept that we have data - a thing that is separate from display. As noted, we don't want to try and think of HTML as some table - it is ONLY for display - its only markup.
So, the first issue we deal with?
Where and how did this data come from in the first place? I mean, it rare as a cold day in hell that the data JUST appears out of now place. So, first up, is do you have, or are you using a database? (and note that since you NOT talked about that database system, this is the VERY reason why you are struggling here).
So, I can pick a repeater, GridView, ListView (my favorite), or many more controls that can display this data for you, but manipulation of the data? Nope - that occurs at the data level - not the UI level. Keep these two concepts separate.
So, where is this data coming from in the first place? Do you have this as a data table and database some place? I mean, you posted a screen shot of the data, but it can't just appear by magic, can it?
So, this is the first issue, first order of the day. Where is this data coming from? That's the first part of this puzzle. That data resides some place, and that is a good thing, but it not a HTML table - it is some data in a system that exists some place, and that is our starting point for this. Be this ms-access, FoxPro, Excel or some such?
that data comes from some place, and it exists. It would not make sense that every time we launch the program, that we re-type the data all over again. So, the where, the when, and the source of this data?
Note how you LEFT OUT this detail!!!! - and that's why we are struggling here!
So, say I have a table with some hotels. Well, then I can render (display) the data as some type of HTML table - and might as well let asp.net do that dirty work for us.
So, say we have this markup. In fact, I used the wizard, AND THEN blew out the sql data source that gets placed on the page (I want more control over the data with code).
So, say we have this markup:
<div id="MyGrid" runat="server" style="width:40%">
<asp:Button ID="cmdAdd" runat="server" Text="+Add New" CssClass="btn" />
<asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn"
OnClick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
</div>
So, I dropped in a grid view. (but, with your sample markup, a listView probably is better).
Now, we have this code to load up the above:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Dim cmdSQL As New SqlCommand("SELECT * FROM tblHotelsA ORDER BY HotelName")
Dim rstData as DataTable = MyrstP(cmdSQL)
GHotels.DataSource = rstData
GHotels.DataBind()
End Sub
Public Function MyrstP(sqlCmd As SqlCommand) As DataTable
Dim rstData As New DataTable
Using sqlCmd
Using conn = New SqlConnection(My.Settings.TEST4)
conn.Open()
sqlCmd.Connection = conn
rstData.Load(sqlCmd.ExecuteReader)
End Using
End Using
Return rstData
End Function
Ok, and now we have this:
Note careful:
We did not write loops to load up the HTML.
We use the ado.net data table to get the data. And THEN SEND that data table to the HTML system to display.
Note how we NOT directly working with the HMTL - since well, it is JUST HTML, and as NO business try to be a data system for us - but is great for display!
So, in above, we have a add new button at the top. That could allow us to add a new row to the data base. But, once again, we would add the new row, and then AGAIN send that data (and our new row) to the Gridview, but AGAIN we don't write HTML, we don't try to modify the HTML, and we still have 100% data operations.
Now, no question we might need some markup to edit a single row. That markup to edit ONE row can then be used for our "edit" button, and even our add new button.
So, markup can be used for data entery, but for display of the table and data? That goes and belongs in the database.
So, in above, we might below the grid, drop in some markup that allows edit of one row.
Say, like this:
<div id="EditRecord" runat="server" style="float:left;display: normal" clientidmode="Static" >
<style>
.iForm label {display:inline-block;width:90px}
.iForm input {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm textarea {border-radius:8px;border-width:1px;margin-bottom:10px}
.iForm input[type=checkbox] {margin-right:8px}
</style>
<div style="float:left" class="iForm">
<label>HotelName</label><asp:TextBox ID="txtHotel" runat="server" f="HOtelName" width="280"></asp:TextBox> <br />
<label>First Name</label><asp:TextBox ID="tFN" runat="server" f="FirstName" Width="140"></asp:TextBox> <br />
<label>Last Name</label><asp:TextBox ID="tLN" runat="server" f="LastName" Width="140"></asp:TextBox> <br />
<label>City</label><asp:TextBox ID="tCity" runat="server" f="City" Width="140"></asp:TextBox> <br />
<label>Province</label><asp:TextBox ID="tProvince" runat="server" f="Province" Width="75"></asp:TextBox> <br />
</div>
<div style="float:left;margin-left:20px" class="iForm">
<label>Description</label> <br />
<asp:TextBox ID="txtNotes" runat="server" Width="400" TextMode="MultiLine"
Height="150px" f="Description" ></asp:TextBox> <br />
<asp:CheckBox ID="chkActive" f="Active" Text=" Active" runat="server" TextAlign="Right" />
<asp:CheckBox ID="chkBalcony" f="Balcony" Text=" Has Balcony" runat="server" TextAlign="Right" />
</div>
<div style="clear:both"></div>
<button id="cmdSave" runat="server" class="btn" onserverclick="cmdSave_ServerClick" >
<span aria-hidden="true" class="glyphicon glyphicon-floppy-saved"> Save</span>
</button>
<button id="cmdCancel" runat="server" class="btn" style="margin-left:15px"
onserverclick="cmdCancel_ServerClick"
>
<span aria-hidden="true" class="glyphicon glyphicon-arrow-left"> Back/Cancel</span>
</button>
<button id="cmdDelete" runat="server" class="btn" style="margin-left:15px">
<span aria-hidden="true" class="glyphicon glyphicon-trash"> Delete</span>
</button>
</div>
So, that is some markup, and then we have tht button click for each row.
Our code for that click can look like this:
Protected Sub cmdEdit_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.NamingContainer
Dim pkID = GHotels.DataKeys(gRow.RowIndex).Item("ID")
Dim cmdSQL As New SqlCommand("SELECT * from tblHotelsA where ID = #ID")
cmdSQL.Parameters.Add("#ID", SqlDbType.Int).Value = pkID
Dim rstData As DataTable = MyrstP(cmdSQL)
Call fLoader(Me.EditRecord, rstData.Rows(0)) ' load up hidden div with data
' hide grid
MyGrid.Style.Add("display", "none")
EditRecord.Style.Add("display", "normal")
ViewState("rstData") = rstData
End Sub
Again, note how we do data operations against the database - NOT the HTML table!!! - we certainly did use the "UI" and row click of the grid to get that one row to work on, but after that we RIGHT BACK to useing datatable, and data operations against the database and NOT AGAINST the HTML markup.
So, when you click on a row, we get the row "PK" data id, pull the data, load up some controls on the page, hide the grid, show the "div" that has above. We now get this:
Now, this post is already a bit long, and I could post more code. So, in above, the save button would:
Send data back to database (again, database - not touch the grid view or "table"
Then we re-load the grid view from database
Then we hide our div to edit, and show the div with the grid view to display any edits we made.
this code:
Protected Sub cmdSave_ServerClick(sender As Object, e As EventArgs)
Dim rstData As DataTable = ViewState("rstData")
Call fWriterW(EditRecord, rstData.Rows(0)) ' div to table
Call SaveTable(rstData, "tblHotelsA") ' send table back to database
LoadGrid() ' refresh grid
MyGrid.Style.Add("display", "normal")
EditRecord.Style.Add("display", "none")
End Sub
So, the FIRST question we have and need to know here?
Where is your data now, how do you plan to load + read this data. This is the first step, and worry about some HTML markup to display that data actually is the easy part - but the source and getting that data - now that's the important part of this question and process.
I should note that I come from a ms-access, VB6, FoxPro background (desktop). So, you note the above style of code - looks a lot like VBA due to my roots. But, I did make + build a few helper routines used above, (like fLoader, fWirter) that makes such code easy to write.
So, your first issue? Where does the data come from now, and have you setup a valid connection and means to pull that data into a "data table", of which we THEN can send to the browser as HTML.
Edit -- I see you note that you have 4 store procedures. So yes then you can pull that data to a datatable, and then send that datatable to a GridView or say a listview.
In fact, given your existing markup, then I would suggest a listview. As noted, I often use the wizard to build the listview (or gridview). I then blow out (delete) the sql data source that the wizard creates, and as noted, removed the extra templates.
So, you have a table layout that would work quite well as a ListView.
So, taking your existing markup, say this:
It will look somthing like this:
<div style="width:60%;padding:25px">
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" class="table table-hover table-bordered" >
<tr runat="server" style="">
<th runat="server">Site Plan</th>
<th runat="server" style="text-align:center">Date<br />(MM/DD/YYYY)</th>
<th runat="server" colspan="2">Number of Days to Complete Action</th>
<th runat="server">PWO</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id ="ECOSubmitRow">
<td>
<asp:Label ID="lblSubmittedToECO" runat="server" Text="Site Plan Submitted to ECO for Approval: "></asp:Label>
</td>
<td>
<asp:Label ID="PlanDate" runat="server" Text="MM/DD/YYYY"></asp:Label>
</td>
<td>
<asp:Label ID="lblPMO" runat="server" Text="PWO: "></asp:Label>
</td>
<td>
<asp:TextBox ID="txtPMO" runat="server"></asp:TextBox>
</td>
</tr>
</ItemTemplate>
</asp:ListView>
So, we have kind of this now:
and in fact, for the actual data, we only need ONE row.
so, looking at this, note how I suggested a list view.
I don't have your data - so, I can't really do a lot in a simple post on SO but lets re-create the first hotel grid, but using the List view.
Note how the layout is "very" simular to a table.
So, for the Hotel grid, using a ListView, then we have this:
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" class="table table-bordered">
<tr runat="server" style="">
<th runat="server">FirstName</th>
<th runat="server">LastName</th>
<th runat="server">HotelName</th>
<th runat="server">Active</th>
<th runat="server">Description</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr style="">
<td><asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstName") %>' /></td>
<td><asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>' /></td>
<td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
<td style="text-align:center">
<asp:CheckBox ID="ActiveCheckBox" runat="server" Checked='<%# Eval("Active") %>' />
</td>
<td><asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' /></td>
</tr>
</ItemTemplate>
</asp:ListView>
Note again, VERY simular to a HTML table, but we use ListView, since it is like GridView a data bound control. And we can then feed it that data table.
So, my code to load this list view, is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadGrid
End If
End Sub
Sub LoadGrid()
Dim cmdSQL = New SqlCommand("SELECT * FROM tblHotelsA ORDER BY HotelName")
Dim rstData As DataTable
rstData = MyrstP(cmdSQL)
ListView1.DataSource = rstData
ListView1.DataBind()
End Sub
And I get this:
So, while the GridView is "quick and dirty" as you layout becomes a little more complex, then ListView becomes a better choice - and its layout VERY much follows a HTML table, but the big deal is of course that you can feed it a data table - so, we don't try to create the HTML table or markup - we setup a layout, and feed it that data table.

Related

How do I read checkbox value and control ID within my datalist?

As part of a sort of photo album I have a datalist that displays a bunch of pictures along with some metadata. This all works nicely.
I want to include a check box that flags individual pictures for deletion. Having checked certain boxes, clicking a 'delete' button will fire off a SQL delete command.
Problem is that I have no idea how to identify which check boxes are ticked.
I'm thinking of some sort of loop routine that will identify which cb's are ticked and then read the label 'picID1' text value for inclusion in the SQL delete command.
How do I assign unique id's to the cb's and labels?
Here's the markup -
<asp:DataList ID="DataList1" runat="Server" DataSourceID="SqlDataSource1" RepeatColumns="3"
RepeatDirection="Horizontal" BorderWidth="0px" CellPadding="3">
<ItemStyle CssClass="item" />
<ItemTemplate>
<table align="left" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
</td>
<td>
<a href='viewphoto_Detailed.aspx?imgID=<%# Eval("imgID") %>'>
<asp:Image ID="picAlbum" runat="server" AlternateText="missing image" ImageUrl='<%# "ShowImage.ashx?id=" & Eval("imgID") %>' Width="300" />
</a>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td nowrap="nowrap" width="100" valign="top">
<a class="photoData">
Entry# <asp:Label ID="picID1" runat="server" Text='<%#Server.HtmlEncode(Eval("imgID").ToString())%>'></asp:Label> <asp:CheckBox ID="CheckBox1" runat="server" /><br />
Filename submitted: <%#Getname(Server.HtmlEncode(Eval("imgFileNameSubmitted").ToString()))%><br />
Filename saved: <%#Getname(Server.HtmlEncode(Eval("imgFileNameSaved").ToString()))%><br />
Location: <%#Getname(Server.HtmlEncode(Eval("imgWhere").ToString()))%>
</a>
</td>
<td>
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
Lots of coffee this morning and a rush of blood to the head and I thought this up.
Seems to work ok...
Dim strPicIDs As String = ""
For Each item As DataListItem In DataList1.Items
If item.ItemType = ListItemType.Item OrElse item.ItemType = ListItemType.AlternatingItem Then
Dim DeleteCheckBox As CheckBox = DirectCast(item.FindControl("DeleteCheckBox"), CheckBox)
Dim picID As Label = DirectCast(item.FindControl("picID"), Label)
If DeleteCheckBox IsNot Nothing Then
If DeleteCheckBox.Checked = True Then
strPicIDs += picID.Text + ","
End If
End If
End If
Next

Binding Repeater with Dictionary<string, Dictionary<int,[object]>

I am new to .NET, so I'm struggling with this. I have a content page, with a repeater control. I have a Dictionary, which is a Dictionary<string, Dictionary<int,[object]>>. I want the value of the controls inside the repeater control to get it from the object attributes - Candidate Name, would be object.CandName, candidate phone would be object.Phone etc.
I am not sure how to use Eval for this type of Dictionary. Most of the examples point to Eval("Value"), but it is not giving the correct value for me. Kindly help!
<asp:Content ID="Content2" ContentPlaceHolderID="content" Runat="Server">
<div id="rcontent">
<table>
<tr>
<td>
<asp:Label ID="lblerror" runat="server" Text="" Visible="true" CssClass="alert"></asp:Label>
</td>
</tr>
</table>
<div id ="rptdiv">
<asp:Repeater ID="Repeater1" runat="server" EnableViewState="false">
<ItemTemplate>
<div id="Div3">
<table class="GridViewStyleNoBorder" width=750px cellspacing="0" border="0" >
<tr>
<td class="PagerStyle" colspan="4">
<asp:Label ID="lblName" Runat="server"
Text='<%= Need the value of the [object].objectproperty from dictionary here %>' />
</td>
</tr>
</table>
</div>
This is my Page_Load code behind - BLDecision is my business layer code, which returns the dictionary and dictionary values are correct. I checked them in debug mode.
Code Behind:
Dictionary(int, Dictionary(int, InterviewFeedback)) ;
CandIntDetails = new Dictionary(int, Dictionary(int, InterviewFeedback))();
BLDecision objBLDecision = new BLDecision();
int ReqCategoryID = 0;
if (Request.QueryString["ReqCategoryID"] != null)
ReqCategoryID = int.Parse(Request.QueryString["ReqCategoryID"].ToString());
CandIntDetails = objBLDecision.GetCandidatesforReqCategory(ReqCategoryID);
Repeater1.DataSource = CandIntDetails;
Repeater1.DataBind();
Should I use from codebehind, can I not do Eval('<% ....%>') in the aspx page?
Thanks in advance for your help.
You cannot do it with only one repeater. Since you have a container inside a container, you need a Repeater inside a repeater:
<asp:Repeater ID="Repeater1" runat="server" EnableViewState="false">
<ItemTemplate>
<div id="Div3">
<table class="GridViewStyleNoBorder" width=750px cellspacing="0" border="0" >
<asp:Repeater ID="Repeater2" runat="server" DataSource='<%# Eval("Value")' >
<ItemTemplate>
<tr>
<td class="PagerStyle" colspan="4">
<asp:Label ID="lblName" Runat="server"
Text='<%# Eval("Name") %>' />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
If CandIntDetails is a Dictionary<int, Dictionary<int, InterviewFeedback>>, you need to extract from that the specific collection you want to use as the data source of your repeater. The reason why is because you want to render a collection of InterviewFeedback objects, which CandIntDetails is not. CandIntDetails probably looks something like this:
{
46: {
0: [InterviewFeedback],
1: [InterviewFeedback],
2: [InterviewFeedback]
}
}
It's not clear from your post what the keys are for the inner or outer dictionaries, so this is speculative. If the outer key is the the category ID (not sure why GetCandidatesforReqCategory would return something like that), and if you don't care about the inner dictionary keys, you can extract your data source like this:
Repeater1.DataSource = CandIntDetails[ReqCategoryID].Values;
That will make your data source a straight collection of InterviewFeedback objects. Once that's your data source, you can Eval to access the properties of the InterviewFeedback objects.

ListView programmatically adding row after databind

What I would like to achieve:
I would like a user to be able in insert a row into the listview. BUT not into a database.
What I am stuck on:
Currently I am stuck on the OnItemCommand, i dont seem to be entering the method. Any help would be great Code below.
<LayoutTemplate>
<table>
<th>
</th>
<th class="grayHeader">
<asp:Label ID="lblHeader" runat="server" />
</th>
<tr>
<asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Button runat="server" ID="btnDeletePerson" Text="-" CommandName="deletePerson"/>
</td>
<td>
<asp:Label ID="lblPerson" runat="server" Text='<% #Eval("Person") %>'></asp:Label>
</td>
</tr>
</ItemTemplate>
<InsertItemTemplate>
<tr>
<td>
<asp:Button ID="btnAddUser" runat="server" CommandName="Insert" ext="+" />
</td>
<td>
<asp:TextBox runat="server" ID="txtInsert"></asp:TextBox>
</td>
</tr>
</InsertItemTemplate>
Protected Sub ListGrantee_OnItemCommand(ByVal sender As Object, ByVal e As ListViewCommandEventArgs)
Select Case e.CommandName
Case "Insert"
Dim test As ListViewItem
test = New ListViewItem("test")
listGrantee.Items.Add(test)
Case ""
Case Else
End Select
End Sub
I would save you temporarily created Users in the ListView's Datasource flagged as temporary(add a new DataColumn). Afterwards you have to DataBind the Listview. Store the flag in an invisible control(label) so that it is saved in the ViewState on Postbacks.
Further to my comment - as I understand your problem, your OnItemCommand event handler is not getting triggered. Here's how I set up event handlers (using VS2008).
In the design view for the aspx file, I highlight the control that I am interested in. Then, in the "Properties" window, I click on the Event's button (the little lightning flash), and scroll down the list of events until I find the one I am interested in.
Double click in the column next to the event name - this will bring up the code behind page, with the shell of the event handler in place - including the all important "handles ...." clause.
Now enter your event handling code....
I had viewstate turned off. Which disabled the event mechanism, flipped view state back on problem solved.

DropDownList in ModalPopup/UpdatePanel intermittently does not fire SelectedIndexChanged

I've got a UserControl that's used inside of an UpdatePanel.
The UserControl is a fairly simple form that appears via a ModalPopupExtender (which is also part of the UserControl). There are four DropDownLists, as well as some other UI elements.
Three of the four DropDownLists have AutoPostBack="true", with SelectedIndexChanged events that fire on the server and cause some of the other DropDownLists to rebind.
Two of the three DDL's that AutoPostBack are working fine. One of them, which I only just added, is showing some strange behavior.
Let's say I bind five Items to it: 1, 2, 3, 4, 5. I set the SelectedIndex to 0, which makes 1 the selected item.
If I select 5 and then 1 and keep toggling back and forth, everything works fine. The postback occurs and SelectedIndexChanged fires. Every time.
If I ever select 2 or 4, the postback occurs but SelectedIndexChanged does not fire. Every time.
If I ever select 3, something bizarre happens and sometimes the value of the DDL reverts to 1. Even though breakpoints seem to show that it's not rebinding and no unexpected code is running. I know your first instinct will probably be that I'm wrong about the rebinding code not running, but I have literally been staring at the debugger for hours trying to find my mistake. Lots of breakpoints. I don't get it -- this really isn't that complicated.
But obviously I am missing something.
I've put about four hours into this so far and I think I'm just grinding at this point. I could use another perspective.
HTML (and by the way, DropProtocolCycleID is the problem control):
<asp:Panel ID="PanelPopupAssign" runat="server" Style="display:none; cursor: move; width:325px; background-color:Transparent;">
<BlueUI:Panel runat="server" ID="PanelPatientProtocol" Width="500px" HeaderText="Assign Protocol">
<table cellspacing="5">
<tr>
<td style="width:150px;"></td>
<td style="width:50px;"></td>
<td style="width:125px;"></td>
</tr>
<tr runat="server" id="TableRowCategory">
<td align="right">Category:</td>
<td colspan="2">
<asp:DropDownList runat="server" ID="DropProtocolCategories" CausesValidation="false" autopostback="true"/>
</td>
</tr>
<tr>
<td align="right">Protocol:</td>
<td colspan="2">
<asp:DropDownList ID="DropProtocolID" runat="server" Enabled="false" CausesValidation="false" autopostback="true"/>
<asp:Label ID="LabelProtocolName_SetDate" runat="server" />
</td>
</tr>
<tr>
<td colspan="3">
<table style="margin-left: 120px">
<tr>
<td align="right">Cycle:</td>
<td><asp:DropDownList ID="DropProtocolCycleID" runat="server" autopostback="true" /></td>
</tr>
<tr>
<td align="right">Day:</td>
<td>
<asp:DropDownList ID="DropProtocolCycleDayID" runat="server" Enabled="false" />
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="right">Start Date:</td>
<td colspan="2">
<table>
<tr>
<td>
<asp:Textbox ID="TextProtocolStartDate" runat="server" Width="65px"
BackColor="Transparent" BorderStyle="None" ReadOnly="True" Font-Size="11px"
ForeColor="#1C4071" Font-Names="Verdana" ValidationGroup="AssignProtocol" />
</td>
<td>
<img id="ImageProtocolStartDate"
alt="Calendar"
onclick="CalProtocolStartDate.show();"
class="calendar_button"
src="../../Images/Icons/btn_calendar.gif"
width="25"
height="22" />
<asp:RequiredFieldValidator ID="ValRequiredProtocolStartDate" runat="server" display="Dynamic"
ControlToValidate="TextProtocolStartDate" ErrorMessage="Protocol Start Date is required!"
InitialValue="(None)"
Enabled="false" ValidationGroup="AssignProtocol">*</asp:RequiredFieldValidator>
</td>
</tr>
</table>
</td>
</tr>
</table>
<ComponentArt:Calendar runat="server"
id="CalProtocolStartDate"
AllowMonthSelection="false"
AllowMultipleSelection="false"
AllowWeekSelection="false"
CalendarCssClass="calendar"
TitleCssClass="title"
ControlType="Calendar"
DayCssClass="day"
DayHeaderCssClass="dayheader"
DayHoverCssClass="dayhover"
DayNameFormat="FirstTwoLetters"
ImagesBaseUrl="~/Images/Calendar/"
MonthCssClass="month"
NextImageUrl="cal_nextMonth.gif"
NextPrevCssClass="nextprev"
OtherMonthDayCssClass="othermonthday"
PopUp="Custom"
PopUpExpandControlId="ImageProtocolStartDate"
PrevImageUrl="cal_prevMonth.gif"
SelectedDate=""
VisibleDate=""
SelectedDayCssClass="selectedday"
SelectMonthCssClass="selector"
SelectMonthText="¤"
SelectWeekCssClass="selector"
SelectWeekText="»"
SwapDuration="300"
SwapSlide="Linear"
AutoPostBackOnSelectionChanged="False"
PopUpCollapseDuration="0"
ClientSideOnSelectionChanged="onCalProtocolStartDateChange">
<ClientEvents>
<Load EventHandler="Calendar1_onLoad" />
</ClientEvents>
</ComponentArt:Calendar>
<br />
<div style="text-align:center;">
<asp:Button ID="ButtonSaveProtocol" runat="server" Text="Save" ValidationGroup="AssignProtocol" Enabled="false" />
<asp:Button ID="ButtonCancel" runat="server" Text="Cancel" CausesValidation="false" />
</div>
<br />
</BlueUI:Panel>
</asp:Panel>
<ajaxToolkit:ModalPopupExtender id="ModalPopupExtenderAssignProtocol" runat="server"
popupcontrolid="PanelPopupAssign" popupdraghandlecontrolid="PanelPopupAssign" CancelControlID="ButtonCancel"
targetcontrolid="ButtonAssignProtocol" BackgroundCssClass="modalBackground" RepositionMode="RepositionOnWindowResizeAndScroll" >
</ajaxToolkit:ModalPopupExtender>
Relevant codebehind:
Private Sub DropProtocolCycleID_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropProtocolCycleID.SelectedIndexChanged
Me.Show()
Me.SetupDropProtocolCycleDayID()
End Sub
Public Sub Show()
Me.ModalPopupExtenderAssignProtocol.Show()
End Sub
Here's the code where I bind DropProtocolCycleID, if you're interested. It fires in the SelectedIndexChanged event of DropProtocolID, which actually works reliably:
Private Sub SetupDropProtocolCycleID()
If Me.DropProtocolID.SelectedValue = Constants.NothingSelected Then
Me.DropProtocolCycleID.Enabled = False
Exit Sub
Else
Me.DropProtocolCycleID.Enabled = True
End If
Dim ProtocolID As Integer = Me.DropProtocolID.SelectedValue
Dim ProtocolCycles As DataTable = ProtocolManager.GenerateCycleTable(ProtocolID)
Me.DropProtocolCycleID.DataSource = ProtocolCycles
Me.DropProtocolCycleID.DataTextField = "ProtocolCycleNumber"
Me.DropProtocolCycleID.DataValueField = "ProtocolCycleID"
Me.DropProtocolCycleID.DataBind()
If DropProtocolCycleID.Items.Count > 0 Then
Me.DropProtocolCycleID.SelectedIndex = 0
End If
End Sub
ProtocolCycleNumber and ProtocolCycleID are just integers. No chance of anything in there that could interfere with the javascript.
This solution is ugly, but it works, and at this point I need to just get it working and move on.
In a nutshell, I added an invisible button and then made the DropDownList's onchange event click the button with JavaScript whenever it gets changed. This gets around whatever problem we're dealing with here.
I added this JS to the page:
function IndexChanged() {
document.getElementById("ctl00$MainContent$AssignProtocolControl$ButtonIndexChanged").click();
}
I changed the DropDownList to call that:
<asp:DropDownList ID="DropProtocolCycleID" runat="server" onchange="IndexChanged();" />
I added the invisible button:
<asp:Button id="ButtonIndexChanged" Text="Index Changed" style="display: none;" OnClick="DropProtocolCycleID_SelectedIndexChanged" runat="server" />
...And that solved the problem. Please let me know if you discover a better solution.
Oh, and as for the issue with the value sometimes being reverted to 1, it was because I needed to have duplicate values in my ListIems -- the text varied, but the values were sometimes the same.
Apparently when you do that, ViewState botches the job of restoring state and selects the first matched value it finds. So I just made my value a little more elaborate and it works fine now.
I had the same problem, I solved it by adding modalpop.show()
e.g.
AutoPostback=true in the design file
protected void ddlCars_SelectedIndexChanged(object sender, EventArgs e)
{
//Do all your work here
mpEditCars.Show();
}

Enable/Disable table with javascript for multple instances on a single asp age

I just posted one question and got it answered very quickly, thank you.
I have a new problem, being I have a asp label which gets text dynamically set on it during instanation and then I have a onmousedown function tied to it call a javascript function to enable a table area that sitting below that is display - none by default. It all works fine until I put two of these user controls on a page. They both have the specificed label text correct but the javascript enable seems to set the display style attribute of the first usercontrol's table to block instead of the one that is sitting below the label that was clicked. I am sure this is because the script is running on the client side (which I really would like to keep) and all the user controls have the same id name (since they are all instaniations of the same user control) so the javascript to set the style display attribute just gets the first table. I can't seem to think of a good way to either dynamically name the table on instationation so i can specify this "uniquie" id name to the javascript or any other way to do this work.
the user control asp code is below:
function enableDivArea(objName) {
document.getElementById(objName).style.display = "block";
}
function disableDivArea(objName) {
document.getElementById(objName).style.display = "none";
document.forms[0].submit();
}<asp:Label style="cursor:pointer;color:#EA9156;font-family:Arial,Helvetica,sans-serif;font-weight:bold;" ID="m_emailAddressLabel" onmousedown="enableDivArea('EmailFormDivArea');" runat="server" Text="someone#emailaddress.com"></asp:Label>
<table id="EmailFormDivArea" style="display:none; border-style: outset; border-width: thin">
<tr>
<td>To: <asp:Label ID="m_sendEmailToLabel" runat="server" Text=""></asp:Label></td>
<td align="right"><asp:Label onmousedown="disableDivArea('EmailFormDivArea');" id="m_closeLabel" runat="server" Text="close"></asp:Label></td>
</tr>
<tr>
<td><asp:Label ID="m_fromLabel" runat="server" Text="First Name:" Visible="True"></asp:Label></td>
<td><asp:TextBox ID="m_firstNameBox" runat="server" Visible="True"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label ID="Label1" runat="server" Text="Last Name:" Visible="True"></asp:Label></td>
<td><asp:TextBox ID="m_lastNameBox" runat="server" Visible="True"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label ID="Label2" runat="server" Text="E-mail:" Visible="True"></asp:Label></td>
<td><asp:TextBox ID="m_emailBox" runat="server" Visible="True"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label ID="Label3" runat="server" Text="Phone number:" Visible="True"></asp:Label></td>
<td><asp:TextBox ID="m_phoneNumberBox" runat="server" Visible="True"></asp:TextBox></td>
</tr>
<tr>
<td><asp:Label ID="Label4" runat="server" Text="Message:" Visible="True"></asp:Label></td>
<td><asp:TextBox ID="m_messageBox" runat="server" Visible="True" Rows="6" TextMode="MultiLine"></asp:TextBox></td>
</tr>
<tr>
<td colspan="2" align="center"><asp:Button ID="m_sendMessageButton" runat="server" Text="Send Message"
onclick="m_sendMessageButton_Click" /></td>
</tr>
<tr>
<td colspan="2" align="center"><asp:Label runat="server" ID="m_statusLabel" Text="" Visible="true"></asp:Label></td>
</tr>
</table>
and the code behind looks like this:
protected void Page_Load(object sender, EventArgs e)
{
m_emailAddressLabel.Text = this.Parameter;
m_sendEmailToLabel.Text = this.Parameter;
}
Have the table runat server, and let the user control implement INamingContainer.
Construct the ID for the table, and set it programmatically (HtmlTable) in an overridden CreateChildControls, to for instance string.Concat(ID, "table").
EDIT: You also need dynamic ID references in the javascript.
You could use some <asp:PlaceHolder>'s for this, and then set this from code-behind in CreateChildControls,
but maybe it is just easier to move these small scripts inline, and emit scripts from code-behind,
setting client attributes on the asp:Label
Just a quick idea, do the tables both have the same ID? so the script only picks the first it finds?
make the ID unique!
use a asp:table and then
onmousedown="enableDivArea('<%=tableName.ClientID%>');"
First of all you can set the CssClass property for the style.
for hidding:
document.getElementById(theIdOfYourTable).style.display = 'none';
enabled goes the same
oops, I'm sorry, forgot that you can't use <%%> in a server tag (and doing this out of my head). Better for you would be to call the script like this:
onmousedown="enableDivArea(this);"
In your script you don't have to do document.getElementById anymore, since you get the element as a param already now.
I will keep that mind on the last reponse by Henk.
I acutally "cheated" in a new way with the help of your guys information. I dynamically added an attribute to the label that I wanted the javascript to run from the onmousedown from the Page_Load event and formatted the string how I wanted. Here is the line, it works fantastically (at least what I was looking for).
m_emailAddressLabel.Attributes.Add("onmousedown", "enableDivArea('" + EmailFormDivArea.ClientID + "');");
Thanks for all your help.

Resources