Repeater causes postback of the whole page even if it's inside an update panel - asp.net

I have an user control that contains an update panel with a repeater. The repeater has a button used to delete records.
The problem is when I press the delete button, and a record from the repeater gets deleted, a postback on the whole page is triggered. From my understanding, only the section inside the update panel should refresh.
I should also mention that on my master page I have a script manager with the property "EnablePartialRendering" set to true.
Can someone help me with this problem? Thanks in advance.
ASP file:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="ActivityFiles.ascx.cs" Inherits="Training.User_Controls.ActivityFiles" %>
<asp:Repeater ID="FilesRepeater" runat="server">
<HeaderTemplate>
<table class="table table-bordered">
<tr>
<td><b>Name</b></td>
<td><b>Description</b></td>
<td><b>Actions</b></td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<tr>
<td><%# Eval("Name")%></td>
<td><%# Eval("Description")%></td>
<td>
<asp:LinkButton ID="DownloadFile" runat="server" OnClick="DownloadFile_Click" Font-Size="Large"
file-path='<%# Eval("Url")%>'>
<span class="glyphicon glyphicon-floppy-disk text-info" aria-hidden="true"></span>
</asp:LinkButton>
<asp:LinkButton ID="DeleteFile" runat="server" OnClick="DeleteFile_Click" Font-Size="Large"
file-id='<%# Eval("Id") %>'
file-path='<%# Eval("Url") %>'>
<span class="glyphicon glyphicon-trash text-danger" aria-hidden="true"></span>
</asp:LinkButton>
</td>
</tr>
</ContentTemplate>
</asp:UpdatePanel>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
.cs File:
protected void Page_Load(object sender, EventArgs e)
{
activityId = (int)Context.Items["activityId"];
if ( ! IsPostBack && Visible)
{
if (activityId != 0)
{
LoadFiles();
}
}
}
private void LoadFiles()
{
DataTable files = DatabaseHelper.SelectAsDatatable(FilesQueries.GET_ACTIVITY_FILES, new Dictionary<string, object> {
{ "activityId", activityId }
});
FilesRepeater.DataSource = files;
FilesRepeater.DataBind();
if (files.Rows.Count == 0)
{
FilesRepeater.Visible = false;
NoRecords.Visible = true;
}
}
protected void DeleteFile_Click(object sender, EventArgs e)
{
// TODO: modify this function to work only with the fild id
LinkButton deleteButton = (LinkButton)sender;
string fileId = deleteButton.Attributes["file-id"];
string filePath = deleteButton.Attributes["file-path"];
DatabaseHelper.ExecuteNonQuery(FilesQueries.DELETE_FILE, new Dictionary<string, Object>() {
{ "#fileId",fileId },
});
//delete file from disk
string path = Server.MapPath(filePath);
FileInfo file = new FileInfo(path);
if (file.Exists)
{
file.Delete();
}
LoadFiles();
}

Found the solution on another stackoverflow post (See Eugene S answer)
You have to manually add you control to Script Manager. You should do that inside File Repeater's Item created event. Good luck.

Related

AsyncFileUpload and repeater

I have an asyncfileupload control and a repeater that I would like to use to show list of added files. On FileUploadedComplete event I add the new file's name and size to a data table and use it to bind the repeater. I can select a file and add it (SaveAs()), add the info to data table (I can see it is there) but after calling repeater's databind() nothing happens, can't see the file data.
This is what I have (watered down version):
<asp:UpdatePanel runat="server" ID="upnlFU">
<ContentTemplate>
<ajaxToolkit:AsyncFileUpload
runat="server"
ID="fuAttchedDocs"
ThrobberID="myThrobber"
UploaderStyle="Modern"
onuploadedcomplete="fuAttchedDocs_UploadedComplete"
onuploadedfileerror="fuAttchedDocs_UploadedFileError" />
<asp:Repeater runat="server" ID="rptAttachments">
<HeaderTemplate>
<table>
<tr>
<td>File Name</td>
<td>File Size</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("FileName")%></td>
<td><%# Eval("FileSize")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
Code behind:
DataTable dtAttachments;
protected void Page_Load(object sender, EventArgs e)
if (!Page.IsPostBack)
{
dtAttachments = new DataTable();
dtAttachments.Columns.Add("FileName", Type.GetType("System.String"));
dtAttachments.Columns.Add("FileSize", Type.GetType("System.Int32"));
dtAttachments.AcceptChanges();
}
else
{
dtAttachments = (DataTable)ViewState["Attachments"];
}
BindAndSaveAttachmentData();
}
void BindAndSaveAttachmentData()
{
ViewState["Attachments"] = dtAttachments;
rptAttachments.DataSource = dtAttachments;
rptAttachments.DataBind();
}
protected void fuAttchedDocs_UploadedComplete(object sender, AsyncFileUploadEventArgs e)
{
string sFileName = fuAttchedDocs.FileName;
string sFileSize = e.FileSize;
fuAttchedDocs.SaveAs(FilePath.TEMP_FOLDER + sFileName); // Saving to d:\blah\yada temporary folder
dtAttachments.Rows.Add(new object[] { sFileName, int.Parse(sFileSize) });
BindAndSaveAttachmentData();
}
Both file upload and repeater are inside an update panel.

dynamically hiding linkbuttons in a gridview

Here is my template field with 2linkbuttons in a gridview.
How do I hide one of the lnkbuttons depending on the user selection
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<table>
<tr>
<td align="center">
<asp:LinkButton ID="LinkButton1" runat="server" CommandName= "Publish" CommandArgument="<%# Container.DataItemIndex %>"></asp:LinkButton>
</td>
<<td align="center">
<asp:LinkButton ID="LinkButton2" runat="server" CommandName= "Block" HeaderText="Block" CommandArgument="<%# Container.DataItemIndex %>">Block</asp:LinkButton>
</td>
</tr>
</table>
</ItemTemplate>
</asp:TemplateField>
protected void GridView1_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if(Status=="Posted")
{
LinkButton lbtn2 = (LinkButton)e.Row.FindControl("LinkButton2");
lbtn2.Visible = false;
}
if(Status=="Publish")
{
LinkButton lbtn1 = (LinkButton)e.Row.FindControl("LinkButton1");
lbtn1.Visible = false;
}
}
I am doing this using 2 linkbuttons in the template field.
Here if the Status == Posted, then hide LinkButton2.
If ItemType == Published, then hide LinkButton1.
I don't mind using only Linkbutton and set the commandName and commandArgument in aspx.cs`
I am getting an error at...
LinkButton lbtn2 = (LinkButton)e.Row.FindControl("LinkButton2");
lbtn2.Visible = false;
Error: Object reference not set to an instance pointing to lnbt2.Visible = false;
Any clues,
Thanks
Sun
Check to be sure that the row in question is a data row, not a header, etc. The issue is probably because the current row is a header or footer, so it doesn't contain your controls and throws an exception.
protected void GridView1_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
if(Status=="Posted")
{
LinkButton lbtn2 = (LinkButton)e.Row.FindControl("LinkButton2");
lbtn2.Visible = false;
}
if(Status=="Publish")
{
LinkButton lbtn1 = (LinkButton)e.Row.FindControl("LinkButton1");
lbtn1.Visible = false;
}
}
}
I know this is old but I was looking for the same thing; I was able to do it this way also and posting just for reference:
This is in a listview but should be same for gridview:
<asp:LinkButton ID="btnForms" runat="server" Text='MyButton' CommandName="MyCommandName"
Style='<%#GetHiddenTag(Eval("Status").ToString())%>' CommandArgument='<%#Eval("Status")%>' OnClick="MyOnClickCodeBehind" />
Codebehind:
public string GetHiddenTag(string Status)
{
if (Status.ToLower() == "completed")
return "visibility:hidden;";
return "visibility:visible;";
}

How to upload all files in FileUpload controls in ASP.NET Repeater items?

I have an ASP.NET Repeater control with a FileUpload Control in its item template. The ASP.NET Repeater is inside an UpdatePanel as part of a wizard made from an ASP.NET Multiview. I am trying to upload every file in each FileUpload control when I click submit, but the FileUpload controls do not retain a file when I submit the form. Here is the relevant code:
<asp:Repeater ID="RepeaterImages" runat="server" OnItemCommand="RepeaterBoxArts_ItemCommand">
<ItemTemplate>
<tr>
<td class="right">
Choose File:
</td>
<td>
<asp:FileUpload ID="FileUpload" runat="server" />
</td>
</tr>
</ItemTemplate>
foreach (RepeaterItem item in RepeaterImages.Items)
{
if (item.ItemType == ListItemType.Item
|| item.ItemType == ListItemType.AlternatingItem)
{
FileUpload fupload = (FileUpload)item.FindControl("FileUpload");
if (fupload.HasFile)
{
string path = Server.MapPath("~/images/");
fupload.SaveAs(path);
}
}
}
When I click Submit, I want all FileUpload controls with a file to upload their files. However, if I run the step debugger, it shows each FileUpload control as not having a file. It seems to be an issue with postbacks, but I'm not 100% sure.
I had the same problem and solved adding this code
OnClientClick="javascript:document.forms[0].encoding = 'multipart/form-data';"
at the button that will upload all images.
The answer of this problem, I found at this link https://stackoverflow.com/a/217722
See my code below:
In the page ASPX
<asp:Repeater ID="rptUpload" runat="server" OnItemDataBound="rptUpload_ItemDataBound">
<HeaderTemplate>
<table width="100%">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:FileUpload ID="fu" runat="server" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
<p>
<asp:ImageButton ID="btnUpload" runat="server" OnClick="btnUpload" ImageUrl="img/icon_upload.png" OnClientClick="javascript:document.forms[0].encoding = 'multipart/form-data';" />
</p>
In the CodeBehind
protected void btnUpload_Click(object sender, ImageClickEventArgs e)
{
try
{
foreach (RepeaterItem item in rptUpload.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
FileUpload fu = (FileUpload)item.FindControl("fu");
if (fu.HasFile)
{
string path = Server.MapPath("~/images/");
string fileName = Path.GetFileName(fu.FileName);
string fileExt = Path.GetExtension(fu.FileName).ToLower();
fu.SaveAs(path + fileName + fileExt);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}

ListView fields not getting posted

I know I've done something like this before, but I have no idea why it isn't working now. I have a ListView with some textboxes. I want to read the text out of those boxes when I click a button (linkbutton, whatever).
<asp:ListView runat="server" ID="lv_bar" EnableViewState="true">
<LayoutTemplate>
<table>
<tr>
<th>Foo</th>
</tr>
<tr runat="server" id="itemPlaceholder"></tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><asp:LinkButton ID="lb_delete" CausesValidation="false" runat="server" Text="Del" /></td>
<td><asp:TextBox id="txt_foo" runat="server" /></td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:LinkButton ID="lb_add" CausesValidation="false" runat="server" Text="Add" />
And then here's the relevant code-behind stuff:
protected void Page_Load(object sender, EventArgs e)
{
lb_chapter_add.Click += lb_chapter_add_Click;
if (!IsPostBack)
{
lv_chapters.DataSource = new List<Foo>() { new Foo() { Name = "harbl"} };
lv_chapters.DataBind();
}
}
void lb_add_Click(object sender, EventArgs e)
{
foreach (ListViewDataItem item in lv_bar.Items)
{
var txt_foo = (TextBox)item.FindControl("txt_foo");
Response.Write("foo: " + txt_foo.Text);
}
Response.Write("<br />the end");
Response.End();
}
But what I see when I enter some text into txt_foo and click lb_add is just "the end". What am I doing wrong here?
The problem it that you are using a a non persistent object as DataSource.
Due to clicking the button, you generate a postback and lv_chapters does not contain any items. Set a breakpoint in the line where the foreach is and you will see that lv_chapters.Items in null, or that it's Count property returns 0.

Asp.Net ListView how to delete a row without deleting from datasource

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.

Resources