I have table on my asp.net page, and I want to insert new rows.I try to add on every click on button new row which contain cell with FileUpload, but it works only for first time. When I click next time, in my code behind table.
<asp:Panel ID="pnlImages" runat="server" BackColor="Gray" Height="500">
<table id="tblImages" runat="server" width="100%">
<tr>
<td>
<asp:FileUpload ID="FileUpload1" runat="server" />
</td>
</tr>
<tr>
<td align="right" width="100">
<asp:ImageButton ID="imbAddImage" runat="server" ImageUrl="images/plus.png"
Width="48" Height="48" OnClick="imbAddImage_Click"/>
</td>
</tr>
</table>
</asp:Panel>
This is code on button click
protected void imbAddImage_Click(object sender, ImageClickEventArgs e)
{
System.Web.UI.HtmlControls.HtmlTable tbl = (System.Web.UI.HtmlControls.HtmlTable)this.FindControl("tblImages");
System.Web.UI.HtmlControls.HtmlTableRow row = new System.Web.UI.HtmlControls.HtmlTableRow();
System.Web.UI.HtmlControls.HtmlTableCell cell = new System.Web.UI.HtmlControls.HtmlTableCell();
FileUpload temp = new FileUpload();
cell.Controls.Add(temp);
row.Controls.Add(cell); ;
int a=tbl.Controls.Count;
tbl.Controls.AddAt(a-1, row);
}
But problem is that a is always 2. Can anybody help ?
When it comes to dynamic controls, you need to add them on every post back.
You click event handler only adds the newest file and you are not saving the previous ones anywhere. You should add them to the ViewState and query the ViewState to retrieve them.
See this article For a detailed explanation of ViewState.
Related
I'm working with an application develop by ASP.NET, the problem I face is using FormView control, the FormView Control has ItemTemplate, InsertItemTemplate and EditItemTemplate.
Below is the code fragment of InsertItemTemplate:
<asp:FormView ID="FormView1" runat="server" DefaultMode="ReadOnly">
<InsertItemTemplate>
<table cellpadding="0" cellspacing="0">
<tr>
<td>
<asp:Label id="lblPS" runat="server" Text="Process Status"></asp:Label>
</td>
<td>
<asp:DropDownList ID="ddlPS" runat="server"></asp:DropDownList>
</td>
</tr>
<tr>
<td>
<asp:Label id="lblAP" runat="server" Text="Action Plan"></asp:Label>
</td>
<td>
<asp:TextBox id="txtAP" runat="server" Width="230px" TextMode="MultiLine" Rows="5"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2">
<asp:Button ID="btnSubmit" runat="server" Text="Submit" onclick="btnSubmit_Click" />
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
In Page_Load event, I do DataSource Binding into the DropDownList as below:
FormView1.ChangeMode(FormViewMode.Insert);
DropDownList ddlPS = FormView1.FindControl("ddlPS") as DropDownList;
ddlPS.DataSource=GetProcessStatus();
ddlPS.DataBind();
ddlPS.Items.Insert(0, new System.Web.UI.WebControls.ListItem("- Please Select -", "- Please Select -"));
The data binding into DropDownList and the "- Please Select -" was ok.
Here the problem comes, when Submit Button click, I wanted to get user selected DropDownList Value, but the DropDownList.SelectedItem.Text always return me "- Please Select -".
Please advise how can I get the user selected value in InsertItemTemplate.
The problem is with your DataBind on Page Load event.
When you DataBind you clear the existing values and hence loose the selected value.
A drop down list remembers the items in it, so you don't need to DataBind on every postback.
Your could should be like this.
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
DropDownList ddlPS = FormView1.FindControl("ddlPS") as DropDownList;
ddlPS.DataSource=GetProcessStatus();
ddlPS.DataBind();
ddlPS.Items.Insert(0, new System.Web.UI.WebControls.ListItem("- Please Select -", "- Please Select -"));
}
}
I have a repeater, on its item_command event i am binding another repeater. And i want to show data according to role in the second repeater. For it i want to hide and show some column according to role of users. how can we do it using code behind. Thanks in advance.
My code is
<table id="table1" class="yui" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>
EmpID #
</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<asp:Repeater ID="Repaddressorbbl" runat="server" OnItemCommand="Repaddressorbbl_ItemCommand">
<ItemTemplate>
<tr id="gh" style="cursor: pointer" onclick="Select(this);">
<td style="text-align: center;">
<%#Eval("empid")%>
</td>
<td>
<asp:LinkButton ID="lknumber" runat="server" Text="Edit" CommandName="searchbybbloraddress" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</tbody>
<tfoot>
</tfoot>
</table>
protected void Repaddressorbbl_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "searchbybbloraddress")
{
bind_rep2();
}
}
If you want to databind the second repeater from the ItemCommand in your code behind you have two options.
You could modify the dataset you set as the DataSource of the second repeater and set the sensitive data to an empty string or **.
The other option you have is add a IsVisibleToUser boolean property to your dataset and in your second repeater bind the Visible property to this property.
You can easily modify the data that is given to your DataSource by using a Linq query that produces an anonymous object.
Something like:
Repeater2.DataSource = from d in MyData
select new
{
FirstName = d.FirstName,
LastName = d.LastName,
Salary = d.Salary,
IsVisibleToUser = CurrentUser.IsInRole(...)
}
Simple way is use javascript and use Display:none when hide and create function which is Show it when you want.
Am not sure why I cannot access my Label control which was inside the Panel and the Panel is inside the DataList
<asp:DataList ID="DataList2" runat="server" DataSourceID="SqlDataSource1" Width="100%">
<ItemTemplate>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<!-- post details -->
<td style="width: 60%">
<asp:Panel ID="panelPostDetails" runat="server" CssClass="postpage_details">
<table border="0" cellpadding="5" cellspacing="0" width="100%">
<tr>
<td colspan="2"><div class="postpage_header"><%# Eval("Heading") %></div></td>
</tr>
<tr>
<td>
<img src="picserver/posts/<%# Eval("ImagePath") %>/1.jpg" alt="preview" style="width: 240px;" />
<div id="morepictures">
<asp:Label ID="lblMorePictures" runat="server" />
</div>
</td>
<td>
<div style="padding: 0px 5px 0px 5px;">
<div>
more stuff here
</div>
</div>
</td>
</tr>
</table>
</asp:Panel>
<asp:RoundedCornersExtender ID="RoundedCornersExtender1" runat="server"
Radius="6"
Corners="All"
TargetControlID="panelPostDetails"></asp:RoundedCornersExtender>
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
but when I tried using "lbl" in Page_Load, it seems it cannot find the control? can you please help me?
ItemDataBound and Page_Load event
---------------------------------
Panel p = DataList2.FindControl("panelPostDetails") as Panel;
Label l = p.FindControl("lblMorePictures") as Label;
l.Text = code;
that code returns Object reference not set to an instance of an object.
Thanks in advance
update:
ItemDataBound and Page_Load event
---------------------------------
Panel p = DataList2.FindControl("panelPostDetails") as Panel;
if(p==null)
{
System.Diagnostic.Debug.WriteLine("panel does not exist");
}
else
{
System.Diagnostic.Debug.WriteLine("panel does exist");
}
output:
panel does not exist
what on earth is going on!?!
Typically, you access controls like this at runtime by handling either the DataList's ItemCreated or ItemDataBound event. Here's a sample event handler:
protected void DataList2_ItemDataBound(object sender, DataListItemEventArgs e) {
if (e.Item.ItemType == ListItemType.Item) {
Label lbl = (Label)e.Item.FindControl("panelPostDetails").FindControl("lblMorePictures");
lbl.Text = code;
}
}
Wire up your the event handler like this:
<asp:DataList ID="DataList2" runat="server" OnItemDataBound="DataList2_ItemDataBound" ...
#Peter's code must work.
you can also try this:
protected void DataList2_ItemDataBound(object sender, DataListItemEventArgs e)
{
string st= (e.Item.FindControl("lblMorePictures") as Label).Text;
}
and put breakpoint to wath to st. In my case I get a text of lblMorePictures.
With my Form View I needed to add CType to the FindControl. I understand DataList doesn't necessarily need the Ctype however it is possible the Panel may need this prefix. In this case frmDelView is the name of my Form View. In my case the code line below is in my PreRender of my form. That was the only place at the time of creating the form it would return the data I needed to pass to a label on a next page of a Wizard Step page. Long story.
Note: my code is vb and not C#. It should be nearly or exactly the same.
CType(frmDelView.FindControl("txtcboDAcct"), TextBox).Text
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.
Through CommandName="Delete" I try to delete a line from the ListView control but not from the datasource. On Pressing Delete I expect the webpage to reload and show me the updated ListView(with one line deleted). But nothing changes, the ListView will display the same content after pressing Delete. What do I do wrong?
<asp:ListView ID="ListView1"
DataSourceID="XmlDataSource1"
ItemContainerId="DataSection"
runat="server">
<LayoutTemplate>
<h3>Protocols to Upload...</h3>
<table border=0 style="background-color:#9C9EFF; width: 100%;">
<tr align=left>
<th>Region/Exam/Program</th><th>Protocol</th><th>Position</th>
</tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><%#XPath("Location/Path")%></td>
<td><%#XPath("Location/Name")%></td>
<td><%#XPath("Location/Position")%></td>
<td style="width:40px">
<asp:LinkButton ID="SelectCategoryButton" runat="server" Text="Select" CommandName="Select"/>
</td>
</tr>
</ItemTemplate>
<SelectedItemTemplate>
<tr id="Tr1" runat="server" style="background-color:#F7F3FF">
<td><%#XPath("Location/Path")%></td>
<td><%#XPath("Location/Name")%></td>
<td><%#XPath("Location/Position")%></td>
<td style="width:40px">
<asp:LinkButton runat="server" ID="SelectCategoryButton" Text="Delete" CommandName="Delete" />
</td>
</tr>
</SelectedItemTemplate>
<%-- <ItemSeparatorTemplate>
<div style="height: 0px;border-top:dashed 1px #ff0000"></div>
</ItemSeparatorTemplate>--%>
</asp:ListView>
<asp:XmlDataSource ID="XmlDataSource1" XPath="HttpRequestBO/ProtocolsDTO/ProtocolDTO" runat="server"
DataFile="~/HttpRequestBo.Sample.xml"></asp:XmlDataSource>
And this is the code behind:
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ListView1_OnItemDeleted(Object sender, ListViewDeletedEventArgs e)
{
if (e.Exception != null)
{
e.ExceptionHandled = true;
}
}
protected void ListView1_OnItemCommand(object sender, ListViewCommandEventArgs e)
{
if (String.Equals(e.CommandName, "Delete"))
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
ListView1.Items.Remove(dataItem);
}
}
If I don't use the e.ExceptionHandled = true;, after pressing the Delete link the web page will come up with a "Specified method is not supported." message. Why?
If I use the above mentioned line, then the page refreshes but I can still see all original lines (although on debugging I can see that the ListVieItem collection now only contains an item less.)
It's because of the DatasourceID parameter, which binds at every single postback on the original file.
What you should do is to bind your list on the first page load only. The delete button will work as you expect then.
--- after comments.
OK.
In fact, the Delete command would work if you had defined the Delete method on your datasource. Since that's not what you want, you must define the ItemCommand event handler
and tell it to remove the ListViewItem that issued the event.
protected void yourListView_OnItemCommand(object sender, ListViewCommandEventArgs e)
{
if (String.Equals(e.CommandName, "Delete"))
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item;
yourListView.Items.Remove(dataItem);
}
}
It will do so without touching the XML file beneath. Do not databind against it, else the "deleted" row will appear again.