Formview.ChangeMode is not working - asp.net

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#

Related

Generating button in backend ASP Repeater and then finding the control in c#

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

Force Visible Property to Apply During Button Click

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.

I can't access the ID nested inside the ListView <itemtemplate>

I am trying to grab the value of the checkbox every time a user checks it using the following markup:
<!---- <asp:CheckBoxList ID="CheckboxWattage" runat="server" RepeatColumns="1" CellSpacing="-1" RepeatDirection="Vertical" RepeatLayout="Flow" TextAlign="Right" Width="300px">
<asp:ListItem text="" value=""></asp:ListItem>
</asp:CheckBoxList>--->
<asp:Listview id="filterListView" runat="server" DataSourceID="" onitemdatabound="filterListView_ItemDataBound" >
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" value='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>' runat="server"/>
<asp:label ID="LabelValue" AssociatedControlID="CheckBox1" runat="server" text='<%#Eval("UDF_WATTAGE") %>' ></asp:label>
<asp:label Style="font-size:12px; font-style: italic;" ID="countLabel" runat="server" text='<%# "(" + DataBinder.Eval(Container.DataItem,"CountofUDF_WATTAGE") +")" %>' ></asp:label>
</br>
</ItemTemplate>
</asp:Listview>
<asp:Button id="wattagebtn" text="Apply" class="btn btn-danger" style="float:right;" onclick="wattageApply_Click" runat="server"></asp:Button>
<asp:Label ID="Label1" runat="server" Text="hi"></asp:Label>
</div>
</div>
code behind update! I think I was able to grab the CheckBox1 ID. how can I grab the checkbox value? When checked?
I will update once I find the solution for anyone that's having the same issue.
UPDATEEE FOUND THE SOLUTION. i had to put if(!IsPostBack){ }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dapter.Fill(ds);
filterListView.DataSource = ds;
filterListView.DataBind();
}
protected void filterListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
}
}
protected void wattageApply_Click(Object sender, System.EventArgs e)
{
foreach (ListViewItem item in filterListView.Items)
{
CheckBox cb = item.FindControl("CheckBox1") as CheckBox;
if (cb.Checked == true)
{
string ch;
Label1.Text = cb.Text;
}
else
{
Label2.Text = cb.Text;
}
}
<asp:ListView ID="ListView1" runat="server" DataSourceID="">
<ItemTemplate>
<div>
<asp:CheckBox ID="CheckBox1" runat="server"
OnCheckedChanged="ListViewItemCheckChanged"
Text='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>' />
.
.
.
</div>
</ItemTemplate>
</asp:ListView>
Code Behind (VB.NET):
Protected Sub ListViewItemCheckChanged(sender As Object, e As EventArgs)
Dim cb As CheckBox = sender
// at this point the variable cb contains the user selected checkbox
End Sub
This will allow you to examine the last Checkbox the user clicked
Keep in mind there will be a postback on each click.
This will give you what you are asking for but is probably not the best interface experience for the user.
Typically when presented with multiple check boxes you allow all the user selections and then process the selections with one postback via some submit style button. This would require:
Looping through the ListView's Item Collection,
For each ListViewDataItem find each CheckBox via FindControl("CheckBox1")
Check for CheckBox1.Checked() and act accordingly
Addendum: How to Loop through ListView Items (VB.NET):
Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Dim cb As CheckBox
For Each lvi As ListViewDataItem In ListView1.Items
cb = lvi.FindControl("CheckBox1")
If cb.Checked Then
...
Else
...
End If
Next
End Sub
Addendum: A word about Checkboxes:
An ASP CheckBox doesn't have a value per se. It's "value" is the Boolean "cb.Checked". But there are two ways you can associate a value with CheckBox
1) If the value is not a security issue and not particulary lengthy you can add an Attribute in the ListView ItemDataBound event
Private Sub ListView1_ItemDataBound(sender As Object, e As ListViewItemEventArgs) Handles ListView1.ItemDataBound
If e.Item.ItemType = ListViewItemType.DataItem Then
Dim drv As DataRowView = e.Item.DataItem
Dim cb As CheckBox = e.Item.FindControl("CheckBox1")
cb.Attributes("some-legal-html-attribute-name") = drv("Some_dataset_field")
End If
End Sub
You are doing something similar with this in your aspx:
<asp:CheckBox ID="CheckBox1" runat="server"
value='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>'/>
the above should render to something like this:
<input id="ListviewMangledprefix_CheckBox1" type="checkbox"
value="[value of UDF_WATTAGE FIELD]" />
Inspect the field in the rendered browser page and see if the "value" attribute is being rendered. If so you should be able to access it in the code behind as:
Dim wattage as String = cb.Attributes("value")
2) Better and more secure would be to implement and use ListView1.DataKeys. But this is a much more extensive topic that you should research when you have time

Get ChekBox Component in Gridview Inside Content Template

I have this aspx snippet:
<asp:updatepanel runat="server" id="resultPanel">
<contenttemplate>
<app:exgridview id="referenceGridView" runat="server" allowpaging="True" allowsorting="True">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:CheckBox ID="checkAllBox" runat="server" CausesValidation="false"></asp:CheckBox>
</HeaderTemplate>
<asp:TemplateField>
.....
How do I get checkAllBox component in .vb code behind?
I have tried this:
referenceGridView.HeaderRow _
.Cells(0).FindControl("checkAllBox")
And
referenceGridView.FindControl("checkAllBox")
but it doesn't work neither.
<asp:GridView OnRowDataBound="MyGridView_RowDataBound" ... />
Then define MyGridView_RowDataBound:
void CustomersGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
Label l = (Label) e.Row.FindControl("lblName");
}
EDITED
You can find the control in GridView.HeaderRow:
NOTE : This code block should be executed after referenceGridView.DataBind(). I am running this in a button click:
Protected Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
Dim checkAllBox As CheckBox = TryCast(referenceGridView.HeaderRow.FindControl("checkAllBox"), CheckBox)
If checkAllBox IsNot Nothing Then
'checkAllBox exists here.
'Place your code for checkAllBox
If checkAllBox.Checked Then
lblResult.Text = "All checked"
Else
lblResult.Text = "All not checked"
End If
End If
End Sub
Presuming that you already have this in page load:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
'clear xml on page load if it contain data
If Not Page.IsPostBack Then
'Getting datasource
'referenceGridView.DataSource = MyDataSource.GetTable()
referenceGridView.DataBind()
End If
End Sub
And my test button in markup:
<asp:button id="btnTest" runat="server" Text="TEST" />
And you can download the test project here.

Problem finding a control within a FormView from code-behind

Here the code behind... I'm trying to retrieve this control so I can add items to the drop down list (I'm retrieving the Role Groups to add to the drop down list in the code-behind)
Protected Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim DDRoleGroups As DropDownList
DDRoleGroups = FormView1.FindControl("DDRoleGroup")
End Sub
Here's the FormView: (I took out most of the fields so it's easier to read)
<asp:FormView ID="FormView1" runat="server" DataKeyNames="ID"
DataSourceID="ObjectDataSource_Vendors"
DefaultMode="Insert" BorderColor="DarkGray"
BorderStyle="Solid" BorderWidth="1px" CellPadding="4" Visible="False">
<EditItemTemplate>
</EditItemTemplate>
<InsertItemTemplate>
<label class="form_label">Role Group:</label><br /><asp:DropDownList ID="DDRoleGroup"
runat="server" Width="175px"
EnableViewState="False">
</asp:DropDownList>
</InsertItemTemplate>
</asp:FormView>
Could it possibly have to do with the fact that it's in the Page_Load sub and the control hasn't acctually loaded yet?
Thanks,
Matt
Your dropdown only exists in Insert mode. Try to implement the formview's ModeChanged event and retrieve the control if CurrentMode == Insert:
protected void FormView1_ModeChanged(object sender, EventArgs e)
{
if (FormView1.CurrentMode == FormViewMode.Insert)
{
DropDownList DDRoleGroups = FormView1.FindControl("DDRoleGroup");
// fill dropdown
}
}
You cannot handle this in Page_Load, as the form has not yet switched into Insert mode.
FindControl on a formview will only work for the template that the FormView's "CurrentMode" property is set to.
In your case, you can only do FindControl for "DDRoleGroups" if your FormView is set to "Insert", since that's the template that your control exists in.
Hope that helps.

Resources