Gridview paging in ModalPopupExtender strange behaviour - c#

I have a modalpopypextender that contains a grid view and I want populate it on button click which does this:
protected void btnViewRecipients_Click(object sender, EventArgs e)
{
ModalPopupExtender1.Show();
BindData();
}
Which is straight forward. BindData does this:
protected void BindData()
{
try
{
SqlCommand sqlCommand = new SqlCommand();
string connectionString = "Data Source=SERVER\\DB1;Initial Catalog=Survey;User ID=abcde;Password=12345;";
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlCommand = sqlConnection.CreateCommand();
sqlCommand.CommandText = "Select * From [Survey].[dbo].[data]";
SqlDataAdapter sda = new SqlDataAdapter(sqlCommand.CommandText, connectionString);
SqlCommandBuilder scb = new SqlCommandBuilder(sda);
//Create a DataTable to hold the query results.
//Fill the DataTable.
sda.Fill(dTable);
//Set the DataGridView DataSource.
gvRecords.DataSource = dTable;
gvRecords.DataBind();
sqlConnection.Close();
}
}
catch (SqlException ex)
{
//Console.WriteLine(ex.StackTrace);
}
}
Now this all works good and I get to see the grid with data. I then turned on autopaging and went ahead to create the call gvRecords_PageIndexChanged. I have also turned on EnableSortingAndPagingCallbacks.
protected void gvRecords_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvRecords.PageIndex = e.NewPageIndex;
gvRecords.DataSource = dTable;
gvRecords.DataBind();
}
This kinda works very strangely. I noticed that when I click a page number, the table becomes blank and shows me EmptyDataText that I defined earlier. But when I close the ModalPopupExtender and open it again (clicking the button again) it shows me the right page and data! e.g. if I clicked page 3, then get a blank table, now reopening the MPE will show me page 3's contents in a gridview. I guess that's the viewstate stored somewhere but why is it that the gridview will not show me the page right away?
I am really stuck at this and failing to understand what I'm missing!
Any help appreciated million times, I have searched and searched online for this but maybe it is so trivial and obvious that no one has ever needed to ask!?!

Edited I've been working with Modals, UpdatePanels and ListViews for years, we'll solve this, but it would be good to see the entire markup.
From your comments I'd suggest;
Put your entire modal markup in the UpdatePanel. Make sure to set the ID and UpdateMode to conditional;
<asp:UpdatePanel ID="upModal" runat="server" UpdateMode="Conditional">
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
I usually use an ASP:Panel as my DIV inside my update panel;
<asp:Panel ID="pnlPopup" runat="server" CssClass="ModalPanel">
Then place your GridView (or in my case ListView) in your panel
In your code behind after you call your gvRecords.Databind(), call upModal.Update()
protected void gvRecords_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvRecords.PageIndex = e.NewPageIndex;
gvRecords.DataSource = dTable;
gvRecords.DataBind();
upModal.Update();
}

I got it working finally, I have had to set PopupControlID to upModal, the updatepanel's ID, as opposed to the inner panel. The targetcontrolID also had to point to a hidden button, as many have found you must when working with MPEs...
Anyway, here goes:
<asp:Button ID="hiddenButton" runat="server" Text="" style="display:none;" />
<ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender1" runat="server" Enabled="True" TargetControlID="hiddenButton" PopupControlID="upModal" BehaviorID="modalbehavior" BackgroundCssClass="modalBackground" OnCancelScript="cancelClick();" CancelControlID="closePopup">
</ajaxToolkit:ModalPopupExtender>
<asp:UpdatePanel runat="server" ID="upModal" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel id="pnlPopup" runat="server" class="ModalPanel" >
<table cellpadding="5" cellspacing="5" class="topBanner" style="width:100%;">
<tr>
<td width="50">
<asp:LinkButton ID="closePopup" runat="server" onclick="LinkButton1_Click" CssClass="ClosePopupCls">Close
[x]</asp:LinkButton>
</td>
<td align="center">
<asp:Label ID="lbl" runat="server" Text="Status"></asp:Label>
</td>
<td width="25">
</td>
</tr>
<tr>
<td colspan="3">
<asp:GridView ID="gvRecords" runat="server" AllowPaging="True"
BackColor="White" EmptyDataText="No Record Found"
EnableSortingAndPagingCallbacks="True" ForeColor="GrayText" Height="600"
onpageindexchanging="gvRecords_PageIndexChanging" Width="800">
</asp:GridView>
</td>
</tr>
</table>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>

Related

How to add multi EditItemTemplate in ListView asp.net

as Title
in my code,there are 2 buttons : "btnA" and "btnB"
When I press btnA , I expect that the ListView will show "EditItemTemplate_Edit" and do not show "EditItemTempPlate_Reset"
btnB is similar to btnA
I already added 2 EditItemTemplates in ListView like this :
<EditItemTemplate>
<tr class="EditItemTemplate" style="text-align: left;" id="EditItemTemplate_Eidt">
<td><asp:Label ID="Label_Factory" runat="server" Text='<%# Eval("test1") %>' /></td>
</tr>
<tr class="EditItemTemplate" style="text-align: left;" id="EditItemTemplate_Reset">
<td><asp:Label ID="Label3" runat="server" Text='<%# Eval("test2") %>' /></td>
</tr>
</EditItemTemplate>
I have already tried using script to set "display" -> "none" but it was not work
plz teach me how to make this work
thanks very much ~"~
I actually suggest in these cases to not even bother with the templates.
You can actually use less markup, less code, and less messy UI for the user.
Why not just let them tab around - make as many changes as they want - almost like a Excel sheet.
then have ONE save button - and on un-do button.
That way:
They just edit - not all this song and dance to hit edit + save buttons
So less UI, less code, and you can just tab around on ANY row - just edit.
Much less code.
So, say we have this markup for the listview.
<style> input {border:none}</style>
<asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" >
<ItemTemplate>
<tr style="">
<td><asp:TextBox ID="txtFirst" runat="server" Text='<%# Eval("Firstname") %>' /></td>
<td><asp:TextBox ID="txtLast" runat="server" Text='<%# Eval("LastName") %>' /></td>
<td><asp:TextBox ID="txtCity" runat="server" Text='<%# Eval("City") %>' /></td>
<td><asp:CheckBox ID="Active" runat="server" Checked='<%# Eval("Active") %>' /></td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table id="itemPlaceholderContainer" runat="server" border="0" class="table table-hover">
<tr runat="server" style="">
<th runat="server">Firstname</th>
<th runat="server">LastName</th>
<th runat="server">City</th>
<th runat="server">Active</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
<asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn-primary" OnClick="cmdSave_Click1" />
<asp:Button ID="cmdAdd" runat="server" Text="Add Row" CssClass="btn-primary" style="margin-left:20px" OnClick="cmdAdd_Click1"/>
<br />
Note how MUCH LESS markup we have.
The code to load this lv looks like this:
private DataTable rstPeople = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
LoadGrid();
ViewState["MyTable"] = rstPeople;
Session["test"] = "hello";
}
else
rstPeople = (DataTable)ViewState["MyTable"];
}
public void LoadGrid()
{
using (SqlCommand cmdSQL = new SqlCommand("SELECT * from People",
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
rstPeople.Load(cmdSQL.ExecuteReader());
ListView1.DataSource = rstPeople;
ListView1.DataBind();
}
}
So we now have this:
So, you are now free to edit - even tab around almost like a Excel sheet. SUPER easy to edit the data - no special buttons to edit/save each row.
Very nice for the user - no huge UI and clicking and messing around to edit.
And the save button code, again REALLY simple since we send the WHOLE grid edits back to the database in one simple edit!!!
(and ONE update operation for the WHOLE grid!!!).
Save button code:
protected void cmdSave_Click1(object sender, EventArgs e)
{
// pull grid rows back to table.
foreach (ListViewItem rRow in ListView1.Items)
{
int RecordPtr = rRow.DataItemIndex;
DataRow OneDataRow;
OneDataRow = rstPeople.Rows[RecordPtr];
OneDataRow["FirstName"] = ((TextBox)rRow.FindControl("txtFirst")).Text;
OneDataRow["LastName"] = ((TextBox)rRow.FindControl("txtLast")).Text;
OneDataRow["City"] = ((TextBox)rRow.FindControl("txtCity")).Text;
OneDataRow["Active"] = ((CheckBox)rRow.FindControl("Active")).Checked;
}
// now send table back to database with updates
string strSQL = "SELECT ID, FirstName, LastName, City, Active from People WHERE ID = 0";
using (SqlCommand cmdSQL = new SqlCommand(strSQL,
new SqlConnection(Properties.Settings.Default.TEST4)))
{
cmdSQL.Connection.Open();
SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);
daupdate.Update(rstPeople);
}
}
So the trick? We persist the data table.
Then to save, you move grid back to data table, and then send the table BACK to the database in one simple update.
And the code to add a new row to the grid is ALSO very easy, we don't have to hit the database, but just add to the table, and then re-bind to the grid.
This code:
protected void cmdAdd_Click1(object sender, EventArgs e)
{
// add a new row to the grid
DataRow OneRow = rstPeople.Rows.Add();
ListView1.DataSource = rstPeople;
ListView1.DataBind();
}
So, notice how we save world poverty, save buckets of code, save buckets of mark-up, and we save buckets of messy UI in which the user has to hit edit/save over and over JUST to edit a few rows.
So, save code, save money, same markup, save messy user interface, provide a MUCH better and seamless user experience.
What more could you want?
Note how we defined the data table at the web page class level - by persisting that data table, then we get all of the wonderful and easy to use benefits above - including MUCH less code, much less markup, and much less user interaction required to edit a few simple rows of data.
And we ONLY send ONE update back to the database to save all rows - all of the dirty work here is thus done by .net for you, and you even wind up with not only MUCH less code, but we hit the database MUCH less for the update.
I did not add a un-do-edits button, but all it would do is call loadGrid again, and that would just re-load the data gain - and thus un-do any of our edits.
(so a un-do button would be a good idea here.)

ListView ItemCommand not being reached on button click

I have an aspx page using listview. The delete button I have needs to execute a sql delete using an ID found in the list view.
ASPX:
<asp:ListView runat="server" ID="ListView2" OnItemDataBound="ListView2_ItemDataBound" OnItemCommand="ListView2_ItemCommand">
<LayoutTemplate>
...
<asp:DataPager runat="server" ID="DataPager" PageSize="10" OnPreRender="DataPager_PreRender">
<Fields>
...
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate>
...
<td runat="server" align="right" colspan="4"><asp:Button ID="deleteRButton" CssClass="Button" runat="server" Text="Delete" CommandName="deleteRButton" OnClientClick="return confirm('You are about to delete this forum response. Are you sure you want to proceed?');" /></td>
...
</ItemTemplate>
<ItemSeparatorTemplate>
</ItemSeparatorTemplate>
</asp:ListView>
Code Behind:
protected void ListView2_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "deleteRButton") //Never makes it here with breakpoints
{
...
//Find label value and execute SQL
}
}
How do I get the button click to execute the Item Command code? I have tried using an OnClick method as well (which fires) but I don't have access to the label ID value that way.
EDIT:
Sharing page load event:
protected void Page_Load(object sender, EventArgs e)
{
GetQuestions(); //builds data table and binds to listview 1
GetAnswers(); //builds data table and binds to listview 2
questionIDBreadCrumb.Text = grabID(); //grabs id from url
//loads the current userID
getUserData();
}
SOLUTION:
Putting the page load events inside if (!ispostback) solved the issue.
if (!IsPostBack)
{
GetQuestions();
GetAnswers();
questionIDBreadCrumb.Text = grabID();
//loads the current userID
getUserData();
//validates questionOwner
}

list view not showing when last record deletes using asp.net

I have a list view grid with delete say I have a pagination links on the page (previous 1 2 Next). when I am trying to delete last record in the second page the listview doesn't show up.I have done binding in the server side and calling when a record delete. If the second page is having more than two records then grid shows. Any one have idea why this issue coming ? But when I reload page the grid showing.
I have a listview grid as
<asp:ListView ID="lvSurvey" runat="server" GroupPlaceholderID="groupPlaceHolder2"
ItemPlaceholderID="itemPlaceHolder2" OnPagePropertiesChanging="OnPagePropertiesChangingSurvey" OnItemCommand="lvSurvey_ItemCommand" >
---
--
</asp:ListView>
I also have pagination as
<asp:PlaceHolder runat="server" ID="groupPlaceHolder2"></asp:PlaceHolder>
<tr>
<td colspan = "3">
<asp:DataPager ID="DataPager2" runat="server" PagedControlID="lvSurvey" PageSize="1">
<Fields>
<asp:NextPreviousPagerField ButtonType="Link" ShowFirstPageButton="false" ShowPreviousPageButton="true"
ShowNextPageButton="false" />
<asp:NumericPagerField ButtonType="Link" />
<asp:NextPreviousPagerField ButtonType="Link" ShowNextPageButton="true" ShowLastPageButton="false" ShowPreviousPageButton = "false" />
</Fields>
</asp:DataPager>
</td>
</tr>
I am able to display record from sql server and also pagination shows in the page. I have a delete button in grid as
<asp:LinkButton ID="lnkDelete" runat="server" CssClass="btn btn-danger" OnClientClick="return getConfirmation(this, 'Please confirm','Are you sure you want to delete?');" CommandArgument='<%# Eval("Order_Survey_ID") + "|" + Eval("Status") %>'
CommandName="DeleteSurveyObject"><i class="glyphicon glyphicon-trash"></i> </asp:LinkButton> <br />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
I am also able to delete and have done server coding for deletion.But when only one record in second link, not able to show listview at the time of deletion.
protected void OnPagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
{
(lvOrderInstall.FindControl("DataPager1") as DataPager).SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
this.GetAllOrderInstall();
TabName.Value = "installation";
}
protected void lvSurvey_ItemCommand(object source, ListViewCommandEventArgs e)
{
if(e.CommandName == "DeleteObject")
{
string[] param = e.CommandArgument.ToString().Split('|');
hfInstallID.Value = param[0].ToString();
DELETEINSTALL(int.Parse(hfInstallID.Value), clsCommon.gConstDTOMode_Delete, clsCommon.gConstActive_Status);
GetAllOrderInstall();
TabName.Value = "installation";
litMsg.Text = "Record deleted successfully";
}
}
Try adding GetAllOrderInstall(); at the end of lvSurvey_ItemCommand function to rebind the list view after updation.
protected void lvSurvey_ItemCommand(object source, ListViewCommandEventArgs e)
{
if(e.CommandName == "DeleteObject")
{
string[] param = e.CommandArgument.ToString().Split('|');
hfInstallID.Value = param[0].ToString();
DELETEINSTALL(int.Parse(hfInstallID.Value), clsCommon.gConstDTOMode_Delete, clsCommon.gConstActive_Status);
GetAllOrderInstall();
TabName.Value = "installation";
litMsg.Text = "Record deleted successfully";
}
GetAllOrderInstall();
}

call listview OnPagePropertiesChanging function from another function in c# asp.net

I have an aspx ListView control, a data pager for paging, paging is working fine. Now I have a dropdown to change page size and show the relevant records in listview. But dropdown not working properly.
I have total 14 records and when i go to 2nd page which has 4 records after that i change dropdown page size to 30 then it does not reflect listview and still showing same 4 records. It changes page number from 2nd to 1st only.
HTML:-
<asp:DropDownList ID="ddlCount" AutoPostBack="true" runat="server" CssClass="form-control"
SelectedIndexChanged="ddlCount_SelectedIndexChanged"> </asp:DropDownList>
<asp:ListView ID="lvParkingLots" runat="server" GroupPlaceholderID="grp" ItemPlaceholderID="item"
GroupItemCount="2" OnPagePropertiesChanging="lvPL_PagePropertiesChanging">
<LayoutTemplate>
<table class="table table-striped tblForm" id="gs">
<tr id="grp" runat="server">
</tr>
<tr class="pagination-listview">
<td></td>
<td style="float: right;">
<asp:DataPager ID="dp" runat="server" PagedControlID="lvParkingLots" PageSize="30">
<Fields>
<asp:NumericPagerField NextPageText="Next" PreviousPageText="Prev" />
</Fields>
</asp:DataPager>
</td>
</tr>
</table>
</LayoutTemplate>
C# function:-
protected void lvPL_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
{
DataPager dp = (lvParkingLots.FindControl("dp") as DataPager);
dp.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
Binddata();
}
I have tried below code but not working..
protected void ddlCount_SelectedIndexChanged(object sender, EventArgs e)
{
Binddata();
}
The first argument to the event is of type object, here it should be the ListView, and the second argument will be PagePropertiesChangingEventArgs which is expecting StartRowIndex and MaximumRow, both are of type integer, so you can call that method like this:
int startRowIndex =2,MaximumRow=3;
lvPL_PagePropertiesChanging(lvSample, new PagePropertiesChangingEventArgs(startRowIndex , MaximumRow));
// where lvSample is the listview
In the case of the second example, you have to call the method like this:
ddlCount_SelectedIndexChanged(ddlCount, EventArgs.Empty);

SQL Databinding to Dropdown Lists in Repeaters C#

Ok guys, so I am trying to bind data into a dropdown list from c#. I am getting a Null error when trying to enter the data into the DDL's. I am using this code for the front end.
<asp:Repeater ID="RepeaterHardDrives" runat="server">
<HeaderTemplate>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:HiddenField ID="hidHardDrivesPackageDefaultID" runat="server" />
<asp:HiddenField ID="hidHardDrivesPackageDefaultPrice" runat="server" />
<span>
<asp:Label runat="server" ID="lbHardDiskPrice" Text="$00.00/mo"></asp:Label></span><label>Hard
Drive:</label><asp:DropDownList ID="ddHardDrive" DataTextField="ItemName" DataValueField="ProductItemID" runat="server" CssClass="lidropdown">
</asp:DropDownList>
<asp:ImageButton runat="server" ID="ShowHarddriveInfo" ImageUrl="/_Images/server_configurator_helpbutton.png"
OnClick="lnkShowHarddriveInfo_OnClick" /></div>
</td>
<td align="right">
<asp:Label runat="server" ID="lbHardDrivesPrice" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
<br />
</FooterTemplate>
</asp:Repeater>
for the backend I am trying to load a dynamic number of Dropdown lists into the repeater then databind them all with the same data.
public void PopulateHardDrives(int intSupportedDrives)
{
PreloadHardDriveRepeater(intSupportedDrives);
SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["connstrname"].ConnectionString);
SqlCommand cmd = new SqlCommand("Prod_SelectIDNamePriceByCategory", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#CategoryCode", "Hard Drive");
DataTable dtHardDrives = new DataTable();
using (conn)
{
conn.Open();
SqlDataReader dr = cmd.ExecuteReader();
dtHardDrives.Load(dr);
ViewState.Add("dtHardDrives", dtHardDrives);
}
foreach (RepeaterItem riHardDrive in RepeaterHardDrives.Items)
{
DropDownList ddHardDrives = (DropDownList)riHardDrive.FindControl("ddHardDrives");
ddHardDrives.DataSource = dtHardDrives;//program gives NULL exception error here(object not set to instance of object however it know the count of the rows it is supposed to be pulling)
ddHardDrives.DataValueField = "ProductItemID";
ddHardDrives.DataTextField = "ItemName";
ddHardDrives.DataBind();
Label lbHardDrive = (Label)riHardDrive.FindControl("lbHardDrivesPrice");
lbHardDrive.Text = String.Format("{0:c}", Convert.ToDecimal("0.00"));
if (riHardDrive.ItemIndex != 0) //We do not want to allow None to be selected on the main drive
{
ddHardDrives.Items.Insert(0, "None");
}
}
}
and last but not least the function to setup the dynamic amount of DDL's looks like this
private void PreloadHardDriveRepeater(int intSupportedDrives)
{
int[] intArrDisks = new int[intSupportedDrives];
for (int intDiskCount = 0; intDiskCount < intArrDisks.Length; intDiskCount++)
{
intArrDisks[intDiskCount] = intDiskCount;
}
RepeaterHardDrives.DataSource = intArrDisks;
RepeaterHardDrives.DataBind();
}
I am calling a list of populate functions in a !page.isPostBack if statement and the only one that is not getting the data is this one with the Drown Lists. It gets the number of Rows(18) from the database, but it it throwing a Null error(Object reference not set to an instance of an object.) I have seen quite a few people have been running into this error while googling the problem, however I could not find a solution that worked for me. The PreloadHardDriveRepeater function seems to work fine when run alone it loads the correct amount of DDL's onto the page.
Thanks ahead of time.
Your control is "ddHardDrive":
<asp:DropDownList ID="ddHardDrive" DataTextField="ItemName" DataValueField="ProductItemID" runat="server" CssClass="lidropdown">
and your code is looking for "ddHardDrives"
riHardDrive.FindControl("ddHardDrives");
This would be easy to notice if you debugged into the function and looked at your variable values right before the exception is thrown.

Categories

Resources