ASP.NET label expression - asp.net

I use this syntax all the time in case of databinding.
<asp:Label ID="myLabel" Text='<%# display_labelText(eval("myValue")) %>' runat="server" />
So I thought it would be easy to use this outside databinding:
<asp:Label ID="myLabel" Text='<%= display_labelText("myValue") %>' runat="server" />
In this case, however, the literal text between the quotes is displayed, and not the intended function value. What is wrong here?

As noted, the "#" is ONLY for use inside of a databound control (listview, repeater, gridview etc.).
However, you CAN use databound expressions for a textbox or a label, but the amount of work is well, not worth it.
However, in place of a "#" (for data bound controls), you can use "=" for any public exposed function in code behind.
BUT ONLY FOR NON server controls!!!
So,say this public function in code behind:
This works:
<h2><%= MyHotel %></h2>
But, this does not:
<asp:TextBox ID="TextBox1" runat="server"
Text='<%= MyHotel %>'
></asp:TextBox>
(becuase TextBox is a server based control - YOU already have full use in code behind.
However, in place of that above expression, I could just as well do this:
<h2 id="myHeader" runat="server"></h2>
And thus in code behind, do this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
myHeader.InnerText = MyHotel()
End If
End Sub
So, any public function in the code behind, then use "=", but NOT for built in server side controls - those expression(s) don't work, but then again, you have full use of such controls in code behind anyway.
However, I do see "over and over" like a broken record people "hand coding" the filling out of controls. That makes VERY little sense in this day an age
Hand coding to fill out values from a database into a web page? That sets back the industry to pre-windows days, and before programs like FoxPro, Ms-access etc came out (in which you don't have to hand-code filling out of controls).
Before such programs, lots of "code" generators appeared. Again, kind of messy.
but, with web forms, gridview, listview, datalist view etc. in most cases can do a LOT of the dirty work for you.
However, I just wrote my own "loader" that simple repeats the code we type over and over for each page. I just "made up/cooked up" my own standard.
So, for each control, I just add a "f" attribute (means data colum field).
So, my code takes a given div, loops the controls, and shoves in the database values for me. You write that code one time, and then use it over and over.
So, then I can drop in a div of controls like this:
<div id="EditRecord" runat="server"
style="float: left; display: none" clientidmode="Static">
<br />
<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>
</div>
<div style="float: left; margin-left: 20px" class="iForm">
<div style="float: left">
<label>Description</label>
<br />
<asp:TextBox ID="txtNotes" runat="server" Width="260px" TextMode="MultiLine"
Height="100px" f="Description"></asp:TextBox>
</div>
etc. etc.
So, now to load the above, I do this:
Dim strSQL As String = "SELECT * FROM tblHotelsA WHERE ID = " & intPK
Dim rstData As DataTable = Myrst(strSQL)
' load up our edit div
fLoader(Me.EditRecord, rstData.Rows(0))
ViewState("PK") = intPK
So, this loads the controls for me, and I get this:
the point is I do/did not have to write code over and over to fill out the "div" of controls.
And in above, I have a routine to do the reverse, (take controls, shove back to data table).
So, my save button code then becomes this:
Dim intPK As Integer = ViewState("PK")
Dim strSQL As String = "SELECT * FROM tblHotelsA WHERE ID = " & intPK
Dim rstData As DataTable = Myrst(strSQL)
Call fWriterW(EditRecord, rstData.Rows(0))
Call MyRstSave(rstData, "tblHotelsA")
' re-fresh grid
LoadGrid()
So, I have fLoader (table row to div)
and hten fWriter (div to table)
And then a save routine.
So, the built in databinding is much like a hug, but without the kiss.
It can bind/fill controls for you, but it does not give you the reverse (sending control values back to the database).
I can post the above loader, and writer code. I have both a c#, and vb version.
It just a simple loop, and looks for the "f" tag inside of the passed div, and then fills out the control value from the database column.
I mean, really, writing the same code over and over to fill out controls on a page makes VERY little sense. With just a wee bit more effort, you can make such code "general" and it can be used for any web page.

Related

Creating Webform IDs dynamically within loop

New to asp.net web forms and I'm having a problem figuring out how to control variables within the loops in my HTML. For Example
<%for (int j = 0; j < Model.Route.Length; j++) { %>
<div class="row">
<hr />
<h3 class="col-lg-12">Route
<%=j %>
</h3>
<div class="row col-lg-12">
<asp:Label ID="Source1_Route1_ID_Label" runat="server" CssClass="col-lg-5">ID</asp:Label>
<asp:TextBox ID="Source1_Route1_ID_Input" runat="server" CssClass="col-lg-6"></asp:TextBox>
</div>
<div class="row col-lg-12">
<asp:Label ID="Source1_Route1_Input_Label" runat="server" CssClass="col-lg-5">Input</asp:Label>
<asp:TextBox ID="Source1_Route1_Input_Input" runat="server" CssClass="col-lg-6"></asp:TextBox>
</div>
<div class="row col-lg-12">
<asp:Label ID="Source1_Route1_Output_Label" runat="server" CssClass="col-lg-5">Output</asp:Label>
<asp:TextBox ID="Source1_Route1_Output_Input" runat="server" CssClass="col-lg-6"></asp:TextBox>
</div>
</div>
<% } %>
<!-- Start Wrapping Routes Rows -->
The above code looks at an array and makes repeats this section for each instance in the array. The problem is that I need control over each of the instances, but right now if in the code behind section I call Source1_Route1_ID.Input.Text = "TEST" It will change all created instances to "TEST". I wanted to create them like <asp:TextBox ID="Source1_Route<%=j%>_ID_Input> but it's throwing an error saying I can't use <%= %> In my ID. Is there an easier way to solve this problem?
In most cases, you don't need or want a loop.
And in most cases, you don't need to inject/put the code in the markup
So, you want to "repeat" somthing over and over?
And then how do you wire up click events etc.? (huge pain point).
So, in webforms land, unlike PHP etc. that inter-mingle code,and use code to spit out markup?
In the VAST majority of cases, with webforms you don't take that design patter approach. More amazing, in 99% of cases you do not need to.
So, a bit of a "gear" shift is required with webforms, and the result is less effort, less code, and no looping in most cases is required.
So, you want to "repeat" something?
Then use a "repeater" (great name, don't you think???).
So,
Say this markup:
<asp:Repeater ID="repHotels" runat="server" >
<ItemTemplate>
<asp:Label ID="txtHotel" runat="server" Width="200px"
Text='<%# Eval("HotelName") %>' Font-Size="X-Large" >
</asp:Label>
<asp:TextBox ID="txtDescription" runat="server"
Text='<%# Eval("Description") %>'
TextMode="MultiLine" Rows="4" Columns="40" Style="margin-left:20px" >
</asp:TextBox>
<asp:Button ID="cmdView" runat="server" Text="View Hotel" CssClass="btn"
style="margin-left:35px;margin-top:25px"
OnClick="cmdView_Click" CommandArgument=<%# Eval("ID") %>
/>
<div style="border-top: 1px solid black;margin-top:8px;margin-bottom:8px"></div>
</ItemTemplate>
</asp:Repeater>
So, you put the markup you want to repeat inside of the item template.
thus, code to fill is this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadData();
}
void LoadData()
{
SqlCommand cmdSQL =
new SqlCommand("SELECT * FROM tblHotelsA ORDER BY HotelName");
repHotels.DataSource = MyRstP(cmdSQL);
repHotels.DataBind();
}
public DataTable MyRstP(SqlCommand cmdSQL)
{
DataTable rstData = new DataTable();
using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (cmdSQL)
{
cmdSQL.Connection = conn;
conn.Open();
rstData.Load(cmdSQL.ExecuteReader());
}
}
return rstData;
}
And now we get/see this:
but, above is NOT really the bonus part.
The button click MOST certainly is the Rossetta stone, since now we have a simple button, but it tied to the row of data.
So this button click code:
protected void cmdView_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
RepeaterItem gRow = (RepeaterItem)btn.NamingContainer;
Debug.Print("row index click = " + gRow.ItemIndex);
Debug.Print("PK passed by button = " + btn.CommandArgument);
Label txtHotel = (Label)gRow.FindControl("txtHotel");
Debug.Print("Value of Hotel = " + txtHotel.Text);
}
Output:
row index click = 1
PK passed by button = 5
Value of Hotel = Inns of Banff
It stands to reason, not "only" would one want to repeat data, but ALSO tie/have/enjoy/use some button click for each row of data.
Note also, do you see any looping??? (nope!!)
Do you see messy code inermixed with the markup? (nope!!!).
So, webforms requires a bit of a different kind of thinking, and design patter approach. Once you get the hang of webforms? You will have sorrowful symphany for how most other framework's function, since as above shows, you don't have to write much code to repeat data, and bonus points is you can simply drop in a button into that repeating data, and get the row information with great ease.

ASP.Net Passing a Variable from VBA on HTML Listview Item template when loading a web page

I have the below code on my aspx page, where a listview is being formed on HTML
´´´
<asp:ListView runat="server"
ID="VistaVehiculos"
DataSourceID="ADSParticipantes"
DataKeyNames="IDInscrito" ItemPlaceholderID="itemPlaceHolder"
OnItemDataBound="VistaVehiculos_ItemDataBound">
<ItemTemplate>
<td>
<asp:Label ID="lNum" runat="server" Height="80px" Width="83px" BackColor="Red"
Style="text-align:center; margin-left:5px; font-size:40px; padding-top:3px; font-family:'Doppio One', sans-serif; font-style:italic"
Text='<%# Eval("Num")%>'/>
<asp:Label ID="lTS" runat="server" Height="80px" BorderStyle="None"
Style="font-size:11px; display:block; margin-top:-80px; margin-left:8px"
text='<%# If(Eval("SEO1") Is DBNull.Value, "", "Correct"))%>'/>
</td>
</ItemTemplate>
<GroupTemplate>
<tr>
<asp:PlaceHolder runat="server" ID="itemPlaceholder" />
</tr>
</GroupTemplate>
<GroupSeparatorTemplate>
<tr id="Tr1" runat="server">
<td style="height:15px"></td>
</tr>
</GroupSeparatorTemplate>
<LayoutTemplate>
<table border="0">
<asp:PlaceHolder runat="server" ID="groupPlaceHolder" />
</table>
</LayoutTemplate>
</asp:ListView>
´´´
In label id=lTS, I evaluate a data field "SEO1"
What I need to do is to set such data field with different values depending on different requirements, to use this page as a template, using load vba procedure.
This case refers to Safety Engine O1 - SEO1, if I need to change by Safety Engine O2, I would evaluate SEO2 data field.
I cannot find control to change text value.
Any help on this?
Ok, first up. Your tags VBA are incorrect VBA is Visual Basic for Applications (that the code system used in Word, Excel, and ms-access.
you are using vb.net - you should change your tags.
As for messing around with that expression? You don't mention if the if() now works?
However, beyond ANY simple Eval() expression, I find it becomes worse then a trip to the dentist to try and burn up a pot of coffee to inject/use/have complex expressions. They are also rather painfull to extend and write and change.
So, I suggest you consider setting the value(s), and writing your code logic in codebehind.
so, I would change this control to this:
<asp:Label ID="lTS" runat="server" Height="80px" BorderStyle="None"
Style="font-size:11px; display:block; margin-top:-80px; margin-left:8px"
text = "" />
Note how it has nothing now. Because we want to apply "more" complex logic to that control, then moving our code to the item data bound event is the place to be!
So, we now will have this:
Protected Sub VistaVehiculos_ItemDataBound(sender As Object, e As ListViewItemEventArgs) Handles VistaVehiculos.ItemDataBound
If e.Item.ItemType = ListViewItemType.DataItem Then
' get the control we are to format
Dim SEOlbl As Label = e.Item.FindControl("ITS")
Dim dRow As DataRowView = e.Item.DataItem
' NOTE IN ABOVE - NOT list view item!!! - but DataRowItem!!!!!!!!!
Dim strResult As String = ""
If dRow("SafteyCase") = "Safety Engine O1" Then
strResult = dRow("SE1").ToString
Else
strResult = dRow("SE2").ToString
End If
If strResult = "" Then
strResult = "NO VALUE"
End If
SEOlbl.Text = strResult
End If
End Sub
note how we are free to get any data column here INCLUDING ones not in the lv layout, but of course they MUST be in the data source.
So, you can conditional test anything you want, and then SHOVE into the label the results of that code - that code can be anything you want.
so, remove your expression from the label, and use code in the data bound event of lv.
Needless to say, you can also use this event to set color of the row, or even text boxes, so for conditonal formatting tricks, you can use the above.

How to add new line items in a APS.net webform and submit to database

Please note: I do not necessarily need working code. I just don't know how to word what I am looking for to even find an answer on the web. I guess i'm just asking for a little guidance on what kind of control I would to use to accomplish my goal.
Basically when I go to a job site I will use different amounts and types of inventory. So one line item would consist of
Item Description
Quantity Used
UsedByTech
I'm collecting these via webform text box. I would like to have a button that says "Add" and then allows me to input another line item, and so on.
Then at some point a submit button on the form would gather those line items and input them in to a MSSQL databse.
I'm currently using ASP.Net framwork and webforms.
Can somone please tell me what kind of control would allow this a may be give me some hints about what to search for?
Ok, this is actually quite easy - but we let asp.net do most of the work for us.
So, we assume we have these two tables:
so, we have a table to list out the Job Sites
And then as per above, we have a table to list out the Job items for each site.
Ok, so we display the Job Sites.
Drop in a Gridview - build it using the wizards:
Now, blow out (delete) the data source from the page - don't need it.
Remove the DataSource setting for the Gridview
And lets drop in a plane jane button into that grid.
Thus, this markup - most of it was generated for me
<div style="padding:25px">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table" Width="40%">
<Columns>
<asp:BoundField DataField="JobSite" HeaderText="JobSite" />
<asp:BoundField DataField="JobDate" HeaderText="JobDate" DataFormatString="{0:yyyy-MM-dd}" />
<asp:BoundField DataField="Foreman" HeaderText="Foreman" />
<asp:BoundField DataField="Description" HeaderText="Description" />
<asp:TemplateField HeaderText="View">
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="View Job" CssClass="btn"
Onclick="cmdView_Click"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
And our code to load this grid is thus 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()
GridView1.DataSource = MyRst("SELECT * from JobSites Order by JobDate")
GridView1.DataBind()
End Sub
Ok, we now have this:
Ok, so now we need to wire up that "view" button.
So, we grab the PK row value - jump to our edit items page;
Protected Sub cmdView_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim gRow As GridViewRow = btn.Parent.Parent
' get PK database ID
Dim PK As Integer = GridView1.DataKeys(gRow.RowIndex).Item("ID")
' Now jump to our job add job items page
Session("JobID") = PK
Response.Redirect("JobAddItems.aspx")
End Sub
So, now we need to build our 2nd page.
I could use a repeater - but I used DataList - to display the ONE job.
I again used the wizards - then blow out the DataSource setting and item on that page.
We then drop in a gridview for the "many" items (the job items).
I now have this:
<br />
<div style="border:solid;border-color:black;width:20%">
<asp:DataList ID="DataList1" runat="server" DataKeyField="ID">
<ItemTemplate>
JobSite:
<asp:Label ID="JobSiteLabel" runat="server" Text='<%# Eval("JobSite") %>' Font-Size="Larger" Font-Bold="true" />
<br />
JobDate:
<asp:Label ID="JobDateLabel" runat="server" Text='<%# Eval("JobDate", "{0:yyyy-MM-dddd}") %>' />
<br />
Foreman:
<asp:Label ID="ForemanLabel" runat="server" Text='<%# Eval("Foreman") %>' />
<br />
Description:
<asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>' />
<br />
<br />
</ItemTemplate>
</asp:DataList>
<br />
</div>
<br />
<div style="float:left">
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" CssClass="table borderhide" Width="30%">
<Columns>
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:TextBox id="txtDesc" runat="server" Text='<%# Eval("ItemDescription") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Qty">
<ItemTemplate>
<asp:TextBox id="txtQty" runat="server" Text='<%# Eval("Qty") %>' TextMode="Number" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Used By">
<ItemTemplate>
<asp:TextBox id="txtUsedBy" runat="server" Text='<%# Eval("UsedBy") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<div style="float:right">
<asp:Button ID="cmdAdd" runat="server" Text="Add Item" CssClass="btn" style="margin-top:-20px" />
</div>
</div>
<div style="clear:both"></div>
<asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel" CssClass="btn" style="margin-left:40px"/>
</div>
Ok, and the code to load this up is this:
We load up the main record - just for display, and then the GridView of child items.
Dim rstJobItems As New DataTable
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ViewState("JobID") = Session("JobId")
LoadData()
Else
rstJobItems = ViewState("JobItems")
End If
End Sub
Sub LoadData()
DataList1.DataSource = MyRst("SELECT * from JobSites WHERE ID = " & ViewState("JobID"))
DataList1.DataBind()
rstJobItems = MyRst("SELECT * FROM JobItems where Job_ID = " & ViewState("JobID"))
GridView1.DataSource = rstJobItems
GridView1.DataBind()
ViewState("JobItems") = rstJobItems
End Sub
Ok, so now on the first page, when we click on a row, we jump to the 2nd page, and we see/have this:
So we need to wire up the button to add a new row.
That code looks like this:
Protected Sub cmdAdd_Click(sender As Object, e As EventArgs) Handles cmdAdd.Click
' user might have done some edits
GridToTable()
' create a new row
Dim NewRow As DataRow = rstJobItems.NewRow
NewRow("Job_id") = ViewState("JobID")
NewRow("Qty") = 0
rstJobItems.Rows.Add(NewRow)
GridView1.DataSource = rstJobItems
GridView1.DataBind()
End Sub
So, say in above, I click the add row, then you will see this:
(in fact I clicked it two times).
Ok, so you are free to tab around - edit data in that grid. You can edit/change existing rows, or add a new row and simple tab around and enter data.
So, now lets wire up the Save button. That save button has to allow and deal with editing rows - and also saving edits - all in ONE shot to the database.
The code for save button is thus this:
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
GridToTable()
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand("SELECT * FROM JobItems WHERE ID = 0", conn)
Dim da As New SqlDataAdapter(cmdSQL)
Dim daU As New SqlCommandBuilder(da)
da.Update(rstJobItems)
End Using
End Using
' data add, and any edit now saved - return to our job site listing page
Response.Redirect("JobSites.aspx")
End Sub
So we send grid to table, and then in ONE database update, send the table back to the database.
Of course after we save, we return back to our first page with the grid now read to edit more.
So, the other routine used in above was sending the Grid (rows) back to the table.
That code is this:
Sub GridToTable()
For Each gRow As GridViewRow In GridView1.Rows
Dim OneRow As DataRow = rstJobItems.Rows(gRow.RowIndex)
OneRow("ItemDescription") = CType(gRow.FindControl("txtDesc"), TextBox).Text
OneRow("Qty") = CType(gRow.FindControl("txtQty"), TextBox).Text
OneRow("UsedBy") = CType(gRow.FindControl("txtUsedBy"), TextBox).Text
Next
End Sub
And of course the cancel button? Well, if you add some rows, or just edit the rows, and hit cancel? Well, we don't save - but just return to the previous page.
eg:
Protected Sub cmdCancel_Click(sender As Object, e As EventArgs) Handles cmdCancel.Click
Response.Redirect("JobSites.aspx")
End Sub
And last but not least, I have a "general" helper routine that simple returns a data table - and I used it several times in above. That routine kind of gives me a FoxPro or MS-Access like ability to get a data table with great ease (in place of typing that same code over and over).
That routine was this:
Public Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New SqlConnection(My.Settings.TEST4)
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
So the above is quite much start to finish. It is of course quick code, and done rather fast/quick for stack overflow. But it is full of great ideas, and as noted, I let the wizards generate most of the markup. (but then remove the data source from the GV, and also the Data source item that gets created in the page.
So in summary:
I did not write most of that markup - I let the wizards generate most of it.
Note how SMALL and relative simple the code bits were. we broke up this into bite sized parts - thus each routine is not a lot of code.
We ALSO let .net built the sql update (and insert) commands for us. this eliminated BOAT LOADS of parameters, and BOATLOADS of work to wire that up. And it also MUCH better for performance, since ado.net is smart - for rows not changed - it don't send the updates to sql server.
Note also how ONE simple update method of
da.Update(rstJobItems)
Handles BOTH edits/updates, an inserts with one command. And we probably could/should drop in a delete row button - and the update would also handle that for us too!!!
So, there is a LOT of great ideas in above, but key concepts are:
Leverage as much as you can the wizards, and built in controls.
Leverage the ability of ado.net to update a table of edits in ONE shot back to the database - and as above shows, SAME single update also works for both inserts and updates at the same time.

asp.net webform vb add new record in a dropdownlist

I Have A Asp.net DropDownList return Data from a 1st table and insert to 2nd table we are inserting Name, Age and position to the 2nd table which the position is returning data from 1st table. the question is where there was a new record we will first add in the 1st table then refresh the page to be able to get the new record. is there is a way when click on dropdownlist at the end of the existing record will be a button "add new" and when click open a popup add new record after that the record add in a 1st table and also be available in the dropdownlist without refresh the page.
is this possible?
Everything up to the issue of NOT wanting to re-fresh the page was great.
How big of a deal is a page post back? I mean if you have several buttons on that form, then the page should be able to tolerate a post back. The reason for this issue/question/point is that WHEN you can allow post-backs, then you have a LOT of options and options that allow a lot of freedom to shove in a dialog pop-up that lets you add a new value to the combo box. And keep in mind that pop option to add a new row to the combo box (dropdownlist) will have to be re-bound with the just newly added row.
If push comes to shove and you REALLY can't tolrate the postback, then you can place the combo box and the "add" to combo box in a update panel.
Next up:
Because we want to pop a dialog? I would recommend adopting jQuery.UI. You have a good chance that jQuery is already included in your project, and thus adopting jQuery.UI is not much more.
There are bootstrap dialogs also - but they are really difficult to work with.
So, lets lay out how this will work.
So, assume we have a little bit of markup a few text boxes, and that dropdown.
Say this:
<div style="padding:5px;float:left;width:250px;text-align:right">
Hotel Name: <asp:TextBox ID="txtHotelName" runat="server" Width="130px" />
<br />
First Name: <asp:TextBox ID="txtFirst" runat="server" Width="130px" />
<br />
Last Name: <asp:TextBox ID="txtLast" runat="server" Text ='<%# Eval("LastName") %>' Width="130px" />
<br />
<div>
City : <asp:DropDownList ID="cboCity" runat="server" DataTextField="City"
DataValueField="City" Width="110px">
</asp:DropDownList>
<div style="float:right;text-align:center;margin-left:4px;margin-top:-1px">
<asp:Button ID="cmdAddCity" runat="server" Text="+"
OnClientClick="AddCity();return false"
style="padding-left:4px;padding-right:8px;width:12px;height:16px;Font-Size:8px"
/>
</div>
</div>
Active: <asp:CheckBox ID="chkActive" runat="server" Checked = '<%# Eval("Active") %>'/>
</div>
Not much to above, and we get this:
Of course on page load, I filled the drop list with code. I have this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadCombo
End If
End Sub
Sub LoadCombo()
Using cmdSQL As New SqlCommand("SELECT City from tblCity ORDER BY City", New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
cboCity.DataSource = cmdSQL.ExecuteReader
cboCity.DataBind()
End Using
End Sub
As noted, we do tend to write statup + load up code in the page load event, but note how I test for ONLY the first post back. Thus, you can quite much write pages that can "survie" a post back.
Ok, so now we need a popup for the jQuery.UI. These are nice, since we don't have to create a whole new web page. The markup for this pop up form (a div) in the current page can/will look like this:
<div id="CityDialog" style="display:Normal" title="Add New City">
<br />
<asp:TextBox ID="txtNewCity" runat="server" Placeholder="Enter New City" ClientIDMode="Static" ></asp:TextBox>
<br />
<br />
<asp:Button ID="cmdOkAddCity" runat="server" Text="Add" ClientIDMode="Static" />
<asp:Button ID="cmdCityCancel" runat="server" Text="Cancel" ClientIDMode="Static"
OnClientClick="$('#CityDialog').dialog('close');return false;"
style="margin-left:20px"/>
</div>
So we add a title to the div. a text box for the new city to add. And two simple standard asp.net buttons.
So, we add above to the above page. and then double click on the cmdOkAdd button, and write the code to add a new row to the combo box.
That code looks like this:
Protected Sub cmdOkAddCity_Click(sender As Object, e As EventArgs) Handles cmdOkAddCity.Click
If txtNewCity.Text <> "" Then
Using cmdSQL As New SqlCommand("INSERT INTO tblCity (City) VALUES (#City)", New SqlConnection(My.Settings.TEST3))
cmdSQL.Parameters.Add("#City", SqlDbType.NVarChar).Value = txtNewCity.Text
cmdSQL.Connection.Open()
cmdSQL.ExecuteNonQuery()
' re-load combo
LoadCombo()
'
' set cbo to the new value we just added
cboCity.Text = txtNewCity.Text
End Using
End If
End Sub
Again, real simple code. (and all easy code behind so far). So what above does is check if the user did enter that new city into the text box, and if yes, then we add the row to the database, and then re-load the combo box and then we SET the combo box to the new city just added. This makes for a easy flow, as the user can then click on that little "+" button beside the combo box, and we pop a dialog, and then the user enters the city, and hits the ok button to run above code stub.
Ok, now we have to setup the jQuery.UI. yes, this is a WEE bit of JavaScript, but NOT much.
So, that "+" button beside the drop down? It is a regular asp button, it is going to pop that jQuery.UI dialog. That button looks like this:
<asp:Button ID="cmdAddCity" runat="server" Text="+"
OnClientClick="AddCity();return false"
style="padding-left:4px;padding-right:8px;width:12px;height:16px;Font-Size:8px"
/>
Note how we have OnClientClick= - that's going to run our JavaScript code stub.
So, say right after that last tag, we have this code:
</form>
<script>
function AddCity() {
$("#CityDialog").dialog({
modal: true,
width: "220px",
resizable: false,
appendTo: "form"
});
}
</script>
Not much code. What that code does it pop the "div" as a nice way cool dialog form. And it turns the rest of the background into a "disabled gray".
So, it works well. And last but not least? We have to hide that dialog div. Remember, don't hide it at first, since we need to double click on the Ok button (add city button) to wire up our add event. Once done, then we hide that div by changing display:normal to Display:none. Eg this:
<div id="CityDialog" style="display:none" title="Add New City">
<br />
<asp:TextBox ID="txtNewCity" runat="server" Placeholder="Enter New City" ClientIDMode="Static" ></asp:TextBox>
<br />
<br />
<asp:Button ID="cmdOkAddCity" runat="server" Text="Add" ClientIDMode="Static" />
... etc. etc.
Ok, now with the above? Well, then we now have this setup:
The code was very helpful but When add all code The popup is not triggering, the second thing How make the dropdown ID connected to the city table ID column not the city column this is my code: Download The Code

Using FindControl: Accessing Controls in a Formview

I'm developing a simple Wedding List application, where guests can reserve the present they want to buy for the bride and groom. The Reserve page wraps a few fields inside a couple of panels, all wrapped inside a FormView.
The user enters their name, email and the quantity of items that they want to reserve, and the page will make the necessary reservations in the DB.
My first problem was that in FormView_ItemCommand, I couldn't reference any of the other controls in the FormView.... I figured this was a case for FindControl - but why do I need to for a Formview when I've never needed it for ListViews or DetailViews?
Secondly, I know the following code works..
Dim oCtrl as TextBox = Me.fvwReservation.FindControl("txtEmail")
Dim Test As String = oCtrl.Text
...but why can't I use...
Dim Test As String = Me.fvwReservation.FindControl("txtEmail").Text
??
Finally, I don't think I need it on this occasion, but I've been researching recursive FindControl variants, but I haven't actually found one that actually compiles! Any suggestions?
It's a lot for one post - thanks in advance.
Gratuitous Code Snippet:
<asp:FormView ID="fvwReservation" runat="Server" DataSourceID="dsGift">
<ItemTemplate>
<asp:Panel runat="server" ID="pnlDetails">
<h3>Reserve Item: <%#Eval("ShortDesc")%></h3>
<p>You have chosen to reserve the <em><%#Eval("LongDesc")%></em> gift.</p>
<p>Please enter your details below to confirm the reservation.</p>
</asp:Panel>
<asp:Panel runat="server" ID="pnlConfirm">
<div class="row">
<asp:Label runat="server" CssClass="label">Name:</asp:Label><asp:TextBox ID="txtName" MaxLength="50" runat="server" CssClass="Field" />
<asp:RequiredFieldValidator ID="rfvName" runat="server" ErrorMessage="You must specify your Name" ControlToValidate="txtName" />
</div>
<div class="row">
<asp:Label runat="server" CssClass="label">Email:</asp:Label><asp:TextBox ID="txtEmail" MaxLength="100" runat="server" CssClass="Field"/>
<asp:RequiredFieldValidator ID="rfvEmail" runat="server" ErrorMessage="You must specify your Email Address" ControlToValidate="txtEmail" />
<asp:RegularExpressionValidator ID="regexEmail" ValidationExpression="^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+#((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$" runat="server" ErrorMessage="Please enter a valid Email Address" ControlToValidate="txtEmail" />
</div>
<div class="row">
<asp:Label runat="server" CssClass="label">Quantity (max <%#Eval("QtyRemaining")%>):</asp:Label><asp:TextBox ID="iQty" MaxLength="2" runat="server" CssClass="Field" />
<asp:RangeValidator ID="rvQty" runat="server" ErrorMessage="The Quantity mmust be between 1 and 10" MinimumValue="1" MaximumValue="10" ControlToValidate="iQty" />
</div>
<div class="row">
<asp:Label runat="server" CssClass="label"> </asp:Label>
<asp:Button ID="btnReserve" Text="Confirm Reservation" CommandName="Reserve" runat="server" />
</div>
</asp:Panel>
</ItemTemplate>
</asp:FormView>
For your second question, FindControl returns a generic Control, and must be cast to the specific type of control in order to obtain access to the properties of that specific type of control.
You can do it in a one liner, like this:
Dim Test As String = CType(Me.fvwReservation.FindControl("txtEmail"), TextBox).Text
Regarding your first question, I would love to know the answer to that as well.
EDIT
Looked through a few other StackOverflow responses (specifically this one and this one). As the controls in the FormView template do not exist until the template is the active template, you cannot directly refer to them in the code behind. Thus, you must use FindControl during an appropriate event to access the controls.
Hmm, even in the FormView templates, I don't think that FindControl will work reliably, typically I would only use that with straight HTML rendered controls, not ASP.net generated ones.
I'm pretty sure that the templated controls should be available in the Server side code, (ie. txtEmail.text) if not, double check the template
A recursive FindControl is also pretty taxing on the Server and potentially unreliable.
You need to use recursive FindControl method in order to access the elements inside the FormView control. There are many implementations available and one of them is linked below:
http://www.highoncoding.com/Articles/606_Creating_a_BetterFindControl_and_MuchBetterFindControl.aspx

Resources