ASP.NET Grid View not updating inside an update panel - c#

Background:
Trying to avoid the complete post back and use partial post back to refresh the data grid. I have checked MSDN, and stack overflow and tried different combinations of the control values for triggering the post back but no luck.
Code
<asp:ScriptManager ID="sm1" runat="server" EnablePartialRendering="true" />
<div>
<asp:UpdatePanel ID="upTest" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true" >
<ContentTemplate>
<asp:GridView ID="gvTest" runat="server" Visible="true" ShowHeader="true" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<div>Document Type</div>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="txtDescription" Style="margin: 2px" MaxLength="254" Text='<%# Bind("DocName") %>' runat="server" Width="200px" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
<label>
<AjaxControlToolkit:AsyncFileUpload ID="AsyncFileUpload1" Width="400px" runat="server"
OnUploadedComplete="AsyncFileUpload1_UploadedComplete" />
</label>
<label id="lblStatus"></label>
</ContentTemplate>
</asp:UpdatePanel>
</div>
Code behind
if (AsyncFileUpload1.HasFile)
{
string strPath = MapPath("~/Uploads/") + Path.GetFileName(e.filename);
AsyncFileUpload1.SaveAs(strPath);
SetGridData(1);
upTest.Update();
}
private void SetGridData(int count)
{
List<Document> Documents = new List<Document>();
Document doc = new Document();
doc.DocName = "test doc";
for (int i = 0; i < count; i++)
{
Documents.Add(doc);
}
gvTest.DataSource = Documents;
gvTest.DataBind();
}
On Page_Load the Grid is loaded with 5 data rows and on the async post back the grid is reset to one data row. While looking at the chrome debugger, I can see the grid data is coming from the server on both Page_Load (5 rows) and async load( 1 data row). But the data grid is not refreshed. I do call the grid.DataBind() during the async post back. Anyone has any ideas whats going on? Am I missing something?
Note: Everything works with normal ASP.Net controls, just dont work with AJAX file upload control

Are you calling the DataBind() method of your GridView within SetGridData? And also add a AsyncPostBackTrigger
Have a look at an example here

try UpdateMode="Always" . it will work

Related

How to create dynamic server controls in C# and how to append more records from the database to repeater control without loading all once again

I have a repeater control on a page that I populate with 10 records from the database. There is a more button on the page; both are inside an update panel. The more button brings the next 10 records from the database. All I want to do is to append the new 10 records to the existing 10 records in the repeater. How would I do this?
I need it to work like Twitter and Facebook and load server side controls while appending new records to repeater control without paging.
This is my .aspx code:
<asp:repeater id="repStd" runat="server" onitemcommand="repStd_ItemCommand"
onitemdatabound="rptCore_ItemDataBound">
<HeaderTemplate>
<asp:Label ID="lnkStdName" runat="server" CommandName="Name"
CssClass="hrefclass">Name</asp:Label>
</HeaderTemplate>
<ItemTemplate>
<div class="headParent" id="STHeader" runat="server">
<asp:Label ID="lblStdName" runat="server"
Text='<%# DataBinder.Eval(Container.DataItem, "Project_Name") %>'></asp:Label>
</div>
<div class="contentParent" id="STcontent" runat="server">
<asp:UpdatePanel ID="UpdatePanelST" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<cc1:AsyncFileUpload ID="STAsyncFileUpload_Pdf" runat="server" Width="500px"
CompleteBackColor="White" OnClientUploadError="STuploadError" OnClientUploadComplete="STuploadComplete"
OnClientUploadStarted="STUploadedStartedPdfFile" UploadingBackColor="#CCDDEE"
UploaderStyle="Modern" ThrobberID="STinProgress"
OnUploadedComplete="STPdf_FileUploadComplete" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</ItemTemplate>
</asp:repeater>
My itemdatabound:
public void rptCore_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
//load controls data and calculations here.. like fileupload control etc
}
According to your requirement use for/Foreach loop by calling table/div structure in place of repeater..
For your logic call 10 records from last index and add in your table/div.
This will solve your problem and it is very effective without making any performance issue..
For eg. follow below logic -
DataTable dt = GetYourRows();
String html = "";
foreach(DataRow dr in dt.Rows)
{
html += "<div>"+dr["column"].ToString();+"</div>";
}
then use your html anywhere in your existing HTML code

gridview Edit Row RegisterPostBackControl

After much searching and testing, it's time to ask for opinions.
A GridView inside an Update Panel with a file upload in an EditItemTemplate:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
AutoGenerateColumns="False" OnRowUpdating="GridView1_RowUpdating"
OnRowDataBound="GridView1_RowDataBound" OnRowEditing="GridView1_RowEditing"
OnRowCancelingEdit="GridView1_RowCancelingEdit" OnRowCommand="GridView1_RowCommand" >
<Columns>
<asp:CommandField ShowEditButton="True" ShowDeleteButton="true" >
</asp:CommandField>
<asp:TemplateField HeaderText="Attachment" SortExpression="FileName">
<EditItemTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" /><br />
<asp:Button ID="btnAddAttachment" runat="server" Text="Upload File" CommandName="AddAttachment"
CommandArgument='<%# Bind("ID") %>' />
</EditItemTemplate>
<ItemTemplate>
<a id="ancLink" runat="server" href='<%# "~/Files/" + (DataBinder.Eval(Container.DataItem,"FileName")) %>'
target="_blank">
<asp:Label ID="lblAnchor" runat="server"></asp:Label></a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Content>
Then for the button in the EditItemTemplate, add the RegisterPostBackControl:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if ((e.Row.RowState == DataControlRowState.Edit) || ((e.Row.RowState & DataControlRowState.Edit) > 0))
{
Button btnAddAttachment = (Button)e.Row.FindControl("btnAddAttachment");
AjaxControlToolkit.ToolkitScriptManager ToolkitScriptManager1 = (AjaxControlToolkit.ToolkitScriptManager)Master.FindControl("ToolkitScriptManager1");
ToolkitScriptManager1.RegisterPostBackControl(btnAddAttachment);
}
}
}
The problem is that the RegisterPostBackControl will not work the first time an attempt is made to upload a file. If a user edits the same row again, the second attempt works fine.
Most likely because the RegisterPostBackControl takes effect on the second post back.
Is there a way to have the button have a full postback the first time?
I know there is an easy way for a work around but this defeats the purpose of the UpdatePanel:
<Triggers>
<asp:PostBackTrigger ControlID="GridView1" />
</Triggers>
And since only Admins will have access to editing, setting the PostBackTrigger for the grid in the code behind for only admins is also an option, but once again, defeating the purpose of the Update Panel.
Any suggestions are welcome.
Depending on lots of factors, you could try the updatepannel option:
ChildrenAsTriggers="true"
It may work as a temporary workaround if you need to push something out now.
Based on your code you have the UpdatePanel using the default values so ChildrenAsTriggers is true and UpdateMode is Always, so you should get a full postback every time.
But I don't see you setting the Gridview's DataSourceID so it won't Databind unless you do so somewhere in the code behind. But you would have to be in edit mode initially in order to even find the control you're trying to register. So you need to register the control when you go into edit mode, try finding and registering the control in the gridview RowEditing event

Nested update panel causing parent update panel to refresh

I think I've tried every combination possible with update panels and I just cant seem to get this to work. I've got an update panel like so:
<asp:UpdatePanel runat="server" ID="upParent" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
Some content...
<div style="width:100%;text-align:center;">
<asp:Label ID="lblMainMessage" runat="server"></asp:Label>
<asp:UpdateProgress AssociatedUpdatePanelID="upParent" ID="UpdateProgress7" runat="server" DisplayAfter="100" DynamicLayout="True" Visible="True">
<ProgressTemplate>
<div class="loader ui-widget-overlay">
Loading data, please wait...<br/><img style="border-style:none;" src="../../Images/ajax-loader.gif" alt="loading" />
</div>
</ProgressTemplate>
</asp:UpdateProgress>
</div>
<div>
<asp:UpdatePanel runat="server" ID="upChild" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
<asp:Timer ID="timerChecklists" runat="server" OnTick="TimerChecklistsTick" Interval="10000"></asp:Timer>
<asp:GridView ID="gvChecklists" runat="server"
AutoGenerateColumns="False" >
<Columns>
<ItemTemplate>
<asp:TemplateField HeaderText="Ques. Ans. Yes">
<ItemTemplate>
<asp:Label ID="lblQuestionsAnsweredYes" runat="server" ForeColor="Green"
Text='<%# DataBinder.Eval(Container, "DataItem.QuestionYesAnswered") %>'
ToolTip="Questions answered Yes."></asp:Label>
</ItemTemplate>
<FooterStyle HorizontalAlign="Center" />
<HeaderStyle HorizontalAlign="Center" />
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Ques. Ans. No">
<ItemTemplate>
<asp:Label ID="lblQuestionsAnsweredNo" runat="server" ForeColor="Red"
Text='<%# DataBinder.Eval(Container, "DataItem.QuestionNoAnswered") %>'
ToolTip="Questions answered No."></asp:Label>
</ItemTemplate>
<FooterStyle HorizontalAlign="Center" />
<HeaderStyle HorizontalAlign="Center" />
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Ques. Ans. N/A">
<ItemTemplate>
<asp:Label ID="lblQuestionsAnsweredNA" runat="server" ForeColor="Gray"
Text='<%# DataBinder.Eval(Container, "DataItem.QuestionNAAnswered") %>'
ToolTip="Questions answered N/A."></asp:Label>
</ItemTemplate>
<FooterStyle HorizontalAlign="Center" />
<HeaderStyle HorizontalAlign="Center" />
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Image ID="imgLoader" runat="server" ImageUrl="/Images/ajax-loader.gif" />
</td>
</tr>
</table>
</div>
<div style="width:100%;text-align:center;">
<asp:Label ID="lblspChecklists2" runat="server"></asp:Label>
</div>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnChecklistExcel"/>
<asp:AsyncPostBackTrigger ControlID="timerChecklists" />
</Triggers>
</asp:UpdatePanel>
What I am trying to accomplish is to sort of lazy load some gridview data due to its size. So what I simply did is wrap the gridview inside an update panel. I then place a timer within this update panel and set it to 10000 (10 seconds) for the tick event. I set the event OnTick as shown:
protected void TimerChecklistsTick(object sender, EventArgs e)
{
LoadChecklistsSubPanel();
timerChecklists.Enabled = false;
imgLoader.Visible = false;
}
The LoadChecklistsSubPanel simply gets a dataset and assigns it to the grid views datasource and does a databind. This all works fine...however my issue is the following:
Note as mentioned a parent update panel and a child update panel. Within this I have an Update progress associated to the update panel upParent. But my issue is when the 10 seconds hits and the timer event is fired this updateprogress is shown (in effect causing my entire page to basically load). I would think that this would not happen given the updatemode is condition and children as triggers is false.
I have also tried ChildrenAsTriggers=true, I've tried to make the update panel mode always, I've tried just about everything but my issue still persists. Right when 10 seconds hits the UpdateProgress (which shows a loading data, please wait overlay is displayed.
Other than that my grid view is getting binded correctly, its getting its data after 10 seconds, etc. My only issue is I cannot seem to understand why the UpdateProgress shows up and overlays my entire screen if all that is happening is my nested sub panel should be updating only.
The fact is that upPanel not updated, you can check this by putting a Label in the upPanel with value="0" and add lblTest.text +=1 under TimerChecklistsTick in codebehind.
you can see that the value don't have any change.
In fact the problem is UpdateProgress control, UpdateProgress control is not a powerful tool and your expectations should not be very high.
if you want a powerful and customizable UpdateProgress you shoud make your own using JavaScript:
<script type="text/javascript">
var postBackElement;
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
function InitializeRequest(sender, args) {
postBackElement = args.get_postBackElement();
if (prm.get_isInAsyncPostBack()) {
args.set_cancel(true);
} else {
//Put your progress UI here
//Check Trigger Id if needed.
//Show an image or Hide another div or ...
}
}
function EndRequest(sender, args) {
}
</script>
But Solution ...
But i was played a little with your code and found that if you remove your timer from inside UpdatePanels and put it outside them totally, your problem will be solved.
</ContentTemplate>
</asp:UpdatePanel>
//Outside the upParent
<asp:Timer ID="timerChecklists" runat="server" OnTick="TimerChecklistsTick" Interval="10000"></asp:Timer>
The problem is persist for any control that placed inside child updatepanels.
i don't know if there are a basis solution or not but as i say UpdateProgress is a simple and quick solution but not good in performance and flexibility totally.
Update
This is simulated code what work for me (ASP.NET 4.5, Chrome 36):
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="Default2.aspx.vb" Inherits="StackOverflowTests_WebVB.net.Default2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="upParent" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
<asp:Label ID="lbl1" runat="server" Text="0"></asp:Label>
<asp:UpdateProgress AssociatedUpdatePanelID="upParent" ID="UpdateProgress7" runat="server" DisplayAfter="100" DynamicLayout="True" Visible="True">
<ProgressTemplate>
<div class="loader ui-widget-overlay">
Loading data, please wait...<br />
<img style="border-style: none;" src="../Images/loading.gif" alt="loading" />
</div>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel runat="server" ID="upChild" UpdateMode="Conditional" ChildrenAsTriggers="False">
<ContentTemplate>
<asp:Label ID="lbl2" runat="server" Text="0"></asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="timerChecklists" />
</Triggers>
</asp:UpdatePanel>
</ContentTemplate>
</asp:UpdatePanel>
<asp:Timer ID="timerChecklists" runat="server" OnTick="TimerChecklistsTick" Interval="1000"></asp:Timer>
</div>
</form>
</body>
</html>
CodeBehind:
Protected Sub TimerChecklistsTick(sender As Object, e As EventArgs)
lbl1.Text += 1
lbl2.Text += 1
End Sub
In output, lbl2 start counting without full postback and without showing the content of UpdateProgress on every Tick.
If you move Timer inside the upChild, you can see that content of UpdateProgress will be shown on evey Tick, but still lbl1 show 0 without any change.

Add Controls to Panel after FormView insert help

Here's my HTML
<asp:UpdatePanel runat="server" ID="panel1" UpdateMode="Conditional">
<ContentTemplate>
<asp:FormView runat="server" ID="formViewUno" DataSourceID="odsBob" DefaultMode="Insert">
<InsertItemTemplate>
<span>Name:</span>
<asp:Literal ID="Literal4" runat="server" Text=" " />
<asp:TextBox runat="server" ID="tbxName" Text='<%# Bind("Name") %>' />
<br />
<span>Age:</span>
<asp:Literal ID="Literal5" runat="server" Text=" " />
<asp:TextBox runat="server" ID="tbxAge" Text='<%# Bind("Age") %>' />
<br />
<span>City:</span>
<asp:Literal ID="Literal6" runat="server" Text=" " />
<asp:TextBox runat="server" ID="tbxCity" Text='<%# Bind("City") %>' />
<br />
<asp:Button ID="Button1" runat="server" CommandName="Insert" Text="Insert" />
</InsertItemTemplate>
</asp:FormView>
<asp:Panel runat="server" ID="msgs">
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
Here's my C#
private void odsBob_Inserted(object sender, ObjectDataSourceStatusEventArgs e)
{
var p = e.ReturnValue as Person;
if (p != null)
{
var msg = new Label
{
Text =
String.Format("{0} [Age:{1}, City:{2}] was successfully added", p.Name, p.Age,
p.City)
};
var br = new LiteralControl { Text = "<br/>" };
msgs.Controls.Add(br);
msgs.Controls.Add(msg);
}
}
How can I persist (add a new one after the insert) the label controls? It is being wiped out. The new one added is added each time correctly. How can I keep the control collection in tact? Thanks for any help.
Cheers,
~ck
It looks like you're dynamically creating a label object during the event handler.
Dynamic controls are problematic because they need to be recreated on every postback. Remember that a postback creates a new instance of your Page object - which means that the controls you added to your last page are gone - your Panel is initialized as empty with each new request, so only the latest literal/label pair will be added.
One solution may be to add all the necessary textual information to Session, and have your Panel generate dynamic labels and literals from whatever is in Session during Prerender.
Another solution would be more complex, but you could have the Panel add labels and literals dynamically during the Init phase. If you can ensure that the same number of controls is added in the same order during Init, then the ViewState for those controls will be properly tracked on each PostBack. You would basically need to store the most recently added label and literal into Session, and have the Panel fetch it out on the next request to ensure it got added back in during Init. You'd also need to store a counter so that the Panel knew how many sets of controls to add during Init.

asp.net with c#

I have one page which is placed in the Master Page.
In the master page I have 1 dropdown and one GridView, dropdown is display the category, based on the dropdown list selection it will display the list of videos in the Grid.
In the content page I have the video player, in the page load it will play the video by default.
But when I choose the drop down list which is available in the master page, the page is refreshing, SO the video is start play from the first.
The content page should not refresh, So the video will continuously play.
How can I stop the page refresh in the content page?
All are in master page.
`<asp:UpdatePanel ID="up1" runat="server" UpdateMode="Conditional">
<asp:DropDownList ID="drp_Channel" Width="220px" CssClass="ddl"
AutoPostBack="true" runat="server"
onselectedindexchanged="drp_Channel_SelectedIndexChanged">
<asp:ListItem>-- Select Channels --</asp:ListItem>
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="up2" runat="server" UpdateMode="Conditional">
<asp:GridView ID="grd_Video" runat="server" AutoGenerateColumns="False" OnRowCommand="LinkName"
GridLines="None" ShowHeader="False" Width="100%" EmptyDataText="No Videos Found" >
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:ImageButton ID="img_Video" runat="server" BorderColor="#666699" CssClass="imgbox"
ImageUrl='<%#(string)FormatImageUrl((string)Eval("Video_Thumbnail")) %>'
CommandName="imgClick" CommandArgument='<%# Bind("Video_ID")%>'
BorderWidth="0px" Height="40px" ToolTip="Click to view video" Width="50px"
BorderStyle="Double" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lnk_VideoName" runat="server" ToolTip="Click to view video"
CommandName="lnkClick" CommandArgument='<%# Bind("Video_ID")%>'
Text='<%# DataBinder.Eval(Container, "DataItem.Video_Name") %>'
CssClass="linkVideo" Width="130px"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<AlternatingRowStyle BackColor="#cccccc" />
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>`
in code behind for binding grid,
DataTable dt1Video = new MDBusiness.MDSUser().GetVideo(intNetId, intChanId, intCatId);
grd_Video.DataSource = dt1Video;
grd_Video.DataBind();
up1.Update();
up2.Update();
Set AutoPostBack = "False" on your dropdownlist to stop the postback from occurring. Users will then be able to change the dropdownlist without anything happening.
You'll need to use AJAX with your dropdownlist if you want to be able to use it without the postback.
for a quick answer
Install ASP.NET AJAX library
Wrap the GridView in a UpdatePanel
Set the trigger to be the DropDownList
Done :)
Remember to see this Screencast... it is exactly what you are after!

Categories

Resources