I'm trying to hide a button and replace it with a label until a query finishes to populate a grid view. My button .aspx page looks like so:
<asp:Panel runat="server" ID="pnlSelect" HorizontalAlign="Center" >
<asp:Label runat="server" Text="Please Select an Item" />
<br />
<br />
<asp:DropDownList runat="server" ID="ddlItems" AutoPostBack="true" />
<br />
<br />
<asp:Button runat="server" ID="btnItemSubmit" Text="Submit" /> <asp:Label runat="server" ID="lblItemSubmit" Text="Please Wait" Visible="false" />
</asp:Panel>
and here is the .aspx.vb code behind that is handling execution:
Protected Sub btnItemSubmit_Click(sender As Object, e As EventArgs) Handles btnItemSubmit.Click
btnItemSubmit.Visible = False
lblItemSubmit.Visible = True
oracleSql()
btnItemSubmit.Visible = True
lblItemSubmit.Visible = False
End Sub
My problem is that the properties don't apply until after the sub finishes execution, at which point no changes are visibly made because the properties immediately went back to how they were originally. Is there a way to get these properties to apply asynchronously?
Edit:
Here is Page_Load
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack Then
'was causing query to reload on button click and default back to first item on list, this way allows it to retain whichever item was selected
'setting postback = false on ddl did not resolve the issue either
Else
Dim oracleConn As New Oracle.DataAccess.Client.OracleConnection
oracleConn.ConnectionString = ConfigurationManager.ConnectionStrings("ConnString").ConnectionString
Dim sql As New Oracle.DataAccess.Client.OracleCommand
sql.CommandType = CommandType.Text
sql.CommandText = "select * from Items order by 1"
sql.Connection = oracleConn
Dim dataAdapter As New Oracle.DataAccess.Client.DataAdapter(sql)
Dim dataSet As New DataSet
dataAdapter.Fill(dataSet)
ddlItems.DataSource = dataSet
ddlItems.DataTextField = "item_name"
ddlItems.DataValueField = "item_id"
ddlItems.DataBind()
End If
End Sub
oracleSql() is similar to this, just binding to a gridview instead of a ddl.
Based on recommendations from JohnPete22, I ended up creating a simple Javascript function to handle this:
<script type="text/javascript">
function hideShowBtn() { document.getElementById('btnItemSubmit').style.visibility = 'hidden'; };
</script>
I then added it to the OnClientClick property of my button:
<asp:Button runat="server" ID="btnItemSubmit" Text="Submit" OnClientClick="hideShowBtn()" />
The button would disappear when clicked and return after PostBack.
Related
So I create a button in the behind code using a function in an Repeater. And then, there's a button that should take these automatically generated buttons (if I check the checkbox in button A, I take the values of row A in repeater,same goes for button B and so on...).
I can see checking the code while debugging that the checkbox are generated correctly. So I should just be able to find it, but can not. Even tho I use the findControl but have not been able to do it.
Here is the code from the front:
<asp:Panel ID="mainPanel" runat="server">
<asp:Repeater ID="repStudents" runat="server">
....
<%# GetButton(Eval("Role").ToString()) %>
....
<asp:LinkButton runat="server" OnClick="showChosen" ClientIDMode="Static"
CausesValidation="true">Save</asp:LinkButton>
And here I generate the button and then try to show the chosen value:
protected string GetButton(string status)
{
string love="";
if(status == "Rel")
{
love = "<input id='relBtn' type='checkbox' runat='server'/>";
}
else
{
love = "<input id='rfBtn' checked type='checkbox' runat='server'/>";
}
return love;
}
protected void showChosen(object sender, EventArgs e)
{
CheckBox cb = (CheckBox)(mainPanel.FindControl("relBtn"));
if(cb.Checked)
lblError.Text = "Checkbox is checked";
else
lblError.Text = "Checkbox is not checked";
divError.Visible = true;
All I keep getting is the Null Reference Exception, even tho, there is just one relBtn in the whole page. If I look into the page generated code, I can see the relBtn, but for some reason, I can not find the Checkbox.
Ok, unless you crossed the desert, climbed mountains, exhausted every "reasonable" alternative?
You have to ask WHY you want to write code to inject a button when THAT is the WHOLE idea of quite near EVERY control from repeater, listview, Gridview and more!
In other words, the need for writing code code, and a GOOD strong case has not been made yet.
and why do we need a huge spectacular earth shaking narrative as to why the approach is being used?
Because in 99% of cases, you don't need to do this, and the data aware controls and darn near the WHOLE asp.net system is designed around you NOT having to take that road.
So, if you have some button, or whatever? Just drop it into the repeater control, and it will "repeat" over and over for you!!!
So, say this simple repeater:
<asp:Repeater ID="Repeater1" runat="server" >
<ItemTemplate>
<div style="border-style:solid;color:black;width:320px;height:450px;float:left;margin-right:10px;margin-bottom:10px">
<div style="text-align:center;padding:2px 10px 2px 10px" class="cards" >
<asp:Button ID="cmdMyView" runat="server" Text="View"
CssClass="btn-info" style="float:right"
CommandArgument = '<%# Eval("ID") %>'
OnClick="cmdMyView_Click" />
<br />
<h3 id="hFighter" runat="server"><%# Eval("Fighter") %></h3>
<asp:Image ID="Image2" runat="server"
ImageUrl = '<%# Eval("ImagePath") %>' Width="170" />
<h4>Engine</h4>
<asp:Label ID="EngineLabel2" runat="server" Text='<%# Eval("Engine") %>' />
<h4>Description</h4>
<asp:Label ID="DescLabel" runat="server" Text='<%# Eval("Description") %>' />
<br />
</div>
</div>
</ItemTemplate>
</asp:Repeater>
Note the button and the plain jane click event for that button.
So, to fill the repeater, we have this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
LoadData()
End If
End Sub
Sub LoadData()
Using conn As New SqlConnection(My.Settings.TEST4)
Dim strSQL As String =
"SELECT * FROM Fighters"
Using cmdSQL As New SqlCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
Repeater1.DataSource = rstData
Repeater1.DataBind()
End Using
End Using
End Sub
And now we see/get this:
And now that button click from above (the view button).
Protected Sub cmdMyView_Click(sender As Object, e As EventArgs)
Dim btn As Button = sender
Dim rRow As RepeaterItem = btn.NamingContainer
Debug.Print("Row index = " & rRow.ItemIndex)
Debug.Print("DATA ID pk = " & btn.CommandArgument)
Dim hFighter As HtmlGenericControl = rRow.FindControl("hFighter")
Debug.Print("Figher name = " & hFighter.InnerText)
End Sub
output:
Row index = 3
DATA ID pk = 4
Figher name = Lockheed Martin F-35 Lightning II
So, note how the the simple button click picks up the current row of data.
From that, we can use find control, or get the "row index" of the click, or in our case, we also included the database PK id in the button command arugment.
So, VERY hard to make a case to do all those "hand stands" to write code to "inject" a button when darn near ALL of the data aware controls will repeat the data AND the controls for you over and over with great ease, and in fact ZERO code to have such buttons or controls repeat for you.
there are RARE cases to write code to inject, but they should be the last resort, since in 99% of cases, no such code is required, and worse yet, when you post-back, such injected controls will NOT persist, and you have to re-inject on every post back for such pages to work.
Edit: So, this could be used
markup:
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<i id="iHotel" runat="server"><%# Eval("HotelName") %></i>
<br />
<asp:CheckBox ID="chkREL" runat="server"
Checked='<%# Eval("Status").ToString() == "Rel" ? true : false %>' />
<br />
<asp:Button ID="Button1" runat="server" Text="Button"
OnClick="Button1_Click" />
<hr />
</ItemTemplate>
</asp:Repeater>
Say code to load:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadData();
}
}
void LoadData()
{
Repeater1.DataSource = General.MyRst("SELECT * FROM tblHotelsA");
Repeater1.DataBind();
}
result is this:
Button click:
protected void Button1_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
RepeaterItem iRow = (RepeaterItem)btn.NamingContainer;
Debug.Print($"Row click index = {iRow.ItemIndex}");
CheckBox chkRel = (CheckBox)iRow.FindControl("chkREL");
Debug.Print($"Check box checked = {chkRel.Checked}");
HtmlGenericControl iHotel = (HtmlGenericControl)iRow.FindControl("iHotel");
Debug.Print($"Hotel name from 'p' item = {iHotel.InnerText}");
}
output:
Row click index = 1
Check box checked = True
Hotel name from 'p' item = Ramada Lodge
I currently have a GridView with two buttons that I have added using the following code;
<asp:GridView ID="gvResults" AutoGenerateColumns="False" runat="server" Font-Size="small"
DataKeyNames="BeachHutID" OnRowDataBound="gvResults_RowDataBound" CssClass="BBCSearch">
<Columns>
<asp:BoundField DataField="BeachHutID" SortExpression="BeachHutID" Visible="false">
</asp:BoundField>
<asp:ImageField DataImageUrlField="HutImage" ItemStyle-Width="1%" ReadOnly="true" />
<asp:BoundField HeaderText="Facilities" DataField="Facilities" Visible="false"></asp:BoundField>
<asp:BoundField HeaderText="Info" DataField="Info" Visible="false"></asp:BoundField>
<asp:TemplateField>
<ItemTemplate>
<asp:PlaceHolder ID="lblHolder" runat="server"></asp:PlaceHolder>
<br />
<asp:PlaceHolder ID="imgHolder" runat="server"></asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnHire" CommandArgument='<%# Eval("BeachHutID") %>' runat="server"
Text="Hire Beach Hut" OnClick="Hire_Click" />
<asp:Button ID="ButtonLogin" CommandArgument='<%# Eval("BeachHutID") %>' runat="server"
Text="Login to Hire Beach Hut" OnClick="Login_Redirect" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
What I want to happen is if the user is logged in, the btnHire button should be enabled and showing and if they're not logged in, ButtonLoggedIn is showing and btnHire is hidden. This is the code I have at the moment;
Public Sub PopulateGrid()
Dim AvailableHuts As New DataTable
AvailableHuts = GetData()
gvResults.DataSource = AvailableHuts
gvResults.DataBind()
gvResults.Enabled = True
'If statement controlling the enabling and disabling of the Beach Hut booking button
If Session("LoginID") = "" Then
For Each rowItem As GridViewRow In gvResults.Rows
rowItem.Cells(5).Enabled = True
Next
End If
lblCaption.Text = "Your search returned " + CStr(AvailableHuts.Rows.Count) + " results"
End Sub
At the moment both buttons are enabled at all times and I'm not sure what I need to add/changed to get the desired result.
From the answer posted by #Andrei, I have added the following to to this Sub;
Protected Sub gvResults_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs) Handles gvResults.RowDataBound
Dim URL(), Text() As String
Dim img As Image
Dim lbl As Label
Dim FacilitiesImg As PlaceHolder = e.Row.FindControl("imgHolder")
Dim Infolbl As PlaceHolder = e.Row.FindControl("lblHolder")
'Added Code from answer
Dim hireBtn As Button = CType(e.Row.FindControl("btnHire"), Button)
hireBtn.Visible = Not String.IsNullOrEmpty(Session("LoginID"))
'Added Code from answer
Dim LoginBtn As Button = CType(e.Row.FindControl("ButtonLogin"), Button)
LoginBtn.Visible = String.IsNullOrEmpty(Session("LoginID"))
If e.Row.RowType = DataControlRowType.DataRow Then
URL = e.Row.DataItem(3).Split(",")
Text = e.Row.DataItem(2).Split(",")
'Add the Facilities Images to the grid Row
For Each item In URL
If item.ToString <> "" Then
img = New Image
img.ImageUrl = item.ToString
FacilitiesImg.Controls.Add(img)
End If
Next
'Add the information to the grid row
'convert # into a carriage return and * into £
For Each item In Text
If item.ToString <> "" Then
lbl = New Label
lbl.Text = Replace(Replace(item.ToString, "#", "<br />"), "*", "£")
Infolbl.Controls.Add(lbl)
End If
Next
End If
End Sub
However I'm receiving the following error when trying to run the program;
Cannot refer to an instance member of a class from within a shared method or shared member initializer without an explicit instance of the class
Any assistance would be much appreciated.
Thanks
Not sure how is your authentication implemented, but let's assume you use HttpContext.Current.Request.IsAuthenticated. Then you can just manipulate Visible property of the buttons in code behind:
btnHire.Visible = HttpContext.Current.Request.IsAuthenticated
ButtonLoggedIn.Visible = Not HttpContext.Current.Request.IsAuthenticated
Update.
Sorry, somehow missed from the post the fact that you seems to be using Session("LoginID") to decide if the use is logged in. The you can do this:
btnHire.Visible = Not String.IsNullOrEmpty(Session("LoginID"))
ButtonLoggedIn.Visible = String.IsNullOrEmpty(Session("LoginID"))
Update 2.
As it turns out, buttons are a part of GridView row. As they are inside the template, you cannot really reach them in the code behind. So you can take two options.
First, you can subscribe to RowDataBound event (which you already did), and inside it do FindControl in the current row to find the necessary button:
Sub gvResults_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
...
Button hireBtn = CType(e.Row.FindControl("btnHire"), Button);
hireBtn.Visible = Not String.IsNullOrEmpty(Session("LoginID"))
and likewise for the second button.
Second, you can try doing it in the markup:
<asp:Button ID="btnHire" CommandArgument='<%# Eval("BeachHutID") %>'
runat="server" Text="Hire Beach Hut" OnClick="Hire_Click"
Visible=<%# String.IsNullOrEmpty(Session("LoginID")) %> />
try
<asp:Button ID="btnHire" CommandArgument='<%# Eval("BeachHutID") %>' runat="server" Visible='<%# islogin()?true:false %>' Text="Hire Beach Hut" OnClick="Hire_Click" />
<asp:Button ID="ButtonLoggedIn" CommandArgument='<%# Eval("BeachHutID") %>' runat="server" Visible='<%# islogin()?false:true %>' Text="Login to Hire Beach Hut" OnClick="Login_Redirect" />
paste this code to aspx.cs page:
Public Shared Function isLogin() As Boolean
Dim stat As Boolean = False
Try
If Session("LoginID") IsNot Nothing AndAlso Session("LoginID") <> "" Then
stat = True
End If
Catch e1 As Exception
stat = False
End Try
Return stat
End Function
Edit2:
Visible='<%# islogin()?false:true %> this means if isLogin() return true then Visible property set to false else it's visible property set to true.
I'm attempting to use Controls.AddAt(), but it apparently breaks controls at later indexes:
Here's my minimal example:
Aspx put in a form:
<asp:DropDownList runat="server" ID="ddl" />
<asp:Button Text="text" runat="server" OnClick="Unnamed2_Click" />
Code Behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
ddl.Items.Add("Click the button")
'Controls.Add(New HyperLink) 'Works fine, but is put at end of collection.
'Controls.AddAt(2 ,New HyperLink) 'Is also safe but I wanted the control first
Controls.AddAt(0, New HyperLink) 'ddl loses it's item after postback
End If
End Sub
On the first postback of the page after calling AddAt, the DropDownList loses it's item. It doesn't matter what kind of control I add even HTMLControls. Viewstate is not disabled.
How do I dynamically add controls without breaking others?
If you used a PlaceHolder to add your HyperLink into, it would not mess up the rest of the page:
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
<asp:DropDownList ID="ddl" EnableViewState="true" runat="server" />
<asp:Button ID="bn1" Text="text" OnClick="Unnamed2_Click" runat="server" />
With code like
Protected Sub Unnamed2_Click(sender As Object, e As EventArgs) Handles bn1.Click
Dim newItem = "Click the button" & DateTime.Now.ToString("HH:mm:ss")
ddl.Items.Add(newItem)
ddl.SelectedIndex = ddl.Items.Count - 1
PlaceHolder1.Controls.Add(New HyperLink With {.ID = "hyp", .Text = "Hyperlink here"})
End Sub
And always give your asp:Controls an ID if they take one.
So, I'm having a slight problem with my code.
I was working on a small school project (recreation of book library) and encountered a problem which I cannot get a grasp of.
So, the user can search for a list of books, and after the list is populated (via DataList control), a small button "Book now" (Reserve) appears which user can click and reserve his book.
This is the code for the DataList control that resides in "Search.aspx"
<asp:DataList ID="DataList1" runat="server" DataKeyField="knjigaId" DataSourceID="SearchSqlDataSource" CssClass="searchControl">
<ItemTemplate>
<div class="pictureOfFoundBook">
<asp:Image ID="pictureOfFoundBook_imageLink" runat="server" ImageUrl='<%#"~/GetImage.aspx?knjigaId=" & Eval("knjigaId") & "&img=naslovnica" %>' />
</div>
<div class="descriptionOfFoundBook">
Naziv: <asp:Label ID="Label1" runat="server" Text='<%# Eval("naziv") %>' /><br />
Godina izdanja: <asp:Label ID="Label2" runat="server" Text='<%# Eval("godinaIzdanja") %>' /><br />
Broj stranica : <asp:Label ID="brojStranicaLabel" runat="server" Text='<%# Eval("brojStranica") %>' /><br />
Izdavač: <asp:Label ID="NazivIzdavacaLabel" runat="server" Text='<%# Eval("NazivIzdavaca") %>' /><br />
Vrsta tiskovine : <asp:Label ID="NazivVrsteTiskovineLabel" runat="server" Text='<%# Eval("NazivVrsteTiskovine") %>' /><br />
Kategorija: <asp:Label ID="NazivKategorijeLabel" runat="server" Text='<%# Eval("NazivKategorije") %>' /><br /><br />
<asp:HyperLink ID="foundBookEditHL_adminOnly" runat="server" NavigateUrl='<%# "~/admin/knjigeEdit.aspx?knjigaId=" & Eval("knjigaId") %>'>Uredi knjigu</asp:HyperLink><br />
<asp:Button ID="rezervacijeButton" runat="server" Text="Rezerviraj" OnClick="rezervacijaClick" CommandArgument='<%# Eval("knjigaId") %>'/><br />
<asp:Label ID="rezStatusLabel" runat="server"></asp:Label>
<asp:PlaceHolder ID="rezStatusPlaceholder" runat="server"></asp:PlaceHolder>
</div>
<hr />
</ItemTemplate>
</asp:DataList>
I've set the DataList1 control as a Friend sub so I can access the controls in it from another sub;
Friend Sub DataList1_ItemCreated(sender As Object, e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DataList1.ItemCreated
End Sub
I was trying to do the following; on the click of a button "rezervacijeButton", a function "rezervacijaClick" runs, which populates the table in the database.
Protected Sub rezervacijaClick(sender As Object, e As System.EventArgs)
Dim Conn As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim sql As New StringBuilder
Dim rezstatus As Label = DataList1.FindControl("rezStatusLabel")
sql.Append("INSERT INTO rezervacije(UserName, knjigaId) VALUES (#UserName, #knjigaId)")
Dim buttonsender As Button = sender
cmd.Parameters.AddWithValue("UserName", User.Identity.Name)
cmd.Parameters.AddWithValue("knjigaId", buttonsender.CommandArgument)
Conn.Open()
cmd.CommandText = sql.ToString
cmd.Connection = Conn
cmd.ExecuteNonQuery()
Conn.Close()
buttonsender.Visible = False
rezstatus.Text = "aaa"
'Try
' rezstatus.Text = "testing..."
'Catch ex As Exception
' exlabel.Text = "POGREŠKA"
' exlabel.ForeColor = Drawing.Color.Red
'End
End Sub
The next thing I wanted to do in the function "rezervacijaClick" was to set the text value of the Label (with ID "rezStatusLabel", which resides inside the DataList1 control) to "SOME TEXT" after the "Reserve" button is clicked.
But after the button click, I get the following error :
Object reference not set to an instance of an object.
Line 21:
Line 22: buttonsender.Visible = False
Line 23: rezstatus.Text = "aaa"
Line 24:
Line 25: 'Try
Your rezstatus object is Nothing (null).
This is happening because you aren't looking in the right place for your label.
Each record of data you bind to the DataList will create a new hierarchy of controls, containers that hold the other controls you have defined in your ItemTemplate.
The immediate descendants of DataList1 will be a collection of DataListItem objects and then you will have your controls inside those.
Since we don't know for sure (unless you know you are only binding one record to the DataList) which DataListItem the desired label will be in, we simply walk backwards up the control tree and find the label from there.
Because you are responding to a button click event in your rezervacijaClick method, the parameter sender will be of type Button and will come from rezervacijeButton, so we can use that information to find your label:
Dim clickedButton As Button = CType(sender, Button) 'convert the sender parameter to the correct type: Button
Dim buttonParent As Control = clickedButton.Parent 'get a reference to the button's parent control
Dim rezstatus As Label = CType(buttonParent.FindControl(""), Label) 'find the label by ID and convert it to a Label as the return type of FindControl is Control
I would recommend that, instead of using the Button click event, you use the DataList.ItemCommand event. It will make your life a lot easier. This event fires whenever a Button is clicked within a row of your DataList control.
This way, you get the index passed in through the DataListCommandEventArgs parameter. then you would just need to update your DataList markup to add the event handler:
<asp:DataList ID="DataList1" runat="server" DataKeyField="knjigaId"
DataSourceID="SearchSqlDataSource" CssClass="searchControl"
ItemCommand="DataList1_ItemCommand" >
And your handler code would look like this:
Protected Sub DataList1_ItemCommand(sender As Object, e As System.EventArgs)
Dim Conn As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("LocalSqlServer").ToString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim sql As New StringBuilder
Dim rezstatus As Label = e.Item.FindControl("rezStatusLabel")
sql.Append("INSERT INTO rezervacije(UserName, knjigaId) VALUES (#UserName, #knjigaId)")
Dim buttonsender As Button = e.Item.FindControl("rezervacijeButton")
cmd.Parameters.AddWithValue("UserName", User.Identity.Name)
cmd.Parameters.AddWithValue("knjigaId", buttonsender.CommandArgument)
Conn.Open()
cmd.CommandText = sql.ToString
cmd.Connection = Conn
cmd.ExecuteNonQuery()
Conn.Close()
buttonsender.Visible = False
rezstatus.Text = "aaa"
End Sub
This is my webpage:
<asp:FormView
ID = "frmView1"
DefaultMode = "Insert"
runat = "server"
>
<ItemTemplate>
Item Template
</ItemTemplate>
<InsertItemTemplate>
Insert Item Template
</InsertItemTemplate>
</asp:FormView>
<asp:Button ID="btnSubmit" Text="Submit" runat="server" />
and this is the code-behind:
Private Sub btnSubmit_Click(sender As Object, e As System.EventArgs) Handles btnSubmit.Click
frmView1.ChangeMode(FormViewMode.ReadOnly)
End Sub
When I'm clicking the btnSubmit the formview is not showing anything! Is this the right way to change mode in code behind?
Moreover, in code behind instead of ChangeMode if write this:
frmView1.DefaultMode = FormViewMode.ReadOnly
forview shows the content of InsertItemTemplate. Could someone please explain what's going on here?
FormView won't show unless you bind, something like this:
using(SqlDataAdapter adapter = new SqlDataAdapter(sql,connection))
{
DataTable table = new DataTable();
adapter.Fill(table);
FormView1.DataSource = table;
FormView1.DataBind();
}
And just add EmptyDataTemplate tag to show empty message if your datasource don't return any value.
<EmptyDataTemplate>
There is nothing to see here.
</EmptyDataTemplate>
follow this tutorial and more about this on MSDN
In your code
<asp:Button ID="btnSubmit" Text="Submit" runat="server" />
must change to
<asp:Button ID="btnSubmit" Text="Submit" runat="server" command="ChangeModeToReadOnly" OnCommand="Button_Command" />
Instead of implementing OnClick event implement this
Protected Sub Button_Command(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.CommandEventArgs)
Select Case e.CommandName
Case "ChangeModeToReadOnly"
frmView1.ChangeMode(FormViewMode.ReadOnly)
End Select
End Sub
You can try with adding the following DataBound function
protected void myFormView_DataBound(object sender, EventArgs e)
{
frmView1.ChangeMode(FormViewMode.ReadOnly);
}
The syntax is in C#