I am trying to find a way to page through a gridview table by year. In my database I have a "season" field and I want all of the data from 2014 shown on one page, all the data from 2013 on another, etc. This would also require different numbers of rows based on the year.
Here is how I would do it. I wouldn't use the default paging of the gridview to handle this. Instead, I would buttons (or linkbuttons) to imitate the paging so that you control the paging. This way, you will be able to handle the change in year as well as control what is displayed.
The Steps are as follows:
1) Add your gridview to the page with a big page size just to display everything
<asp:GridView ID="dgvRequests" runat="server" AutoGenerateColumns="False" PageSize="9999"> </asp:GridView>
2) Bind the Per Year data to it in the code behind since you are display everthing per year in your page load. As well as store a variable to track the year
public int CurrentYear
{
get {
if(ViewState["currentYear"] != null)
return (int)ViewState["currentYear"];
return 2014; //Default
}
set {
_ViewState["currentYear"]= value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
dgvRequests.DataSource = GetYearData(CurrentYear); //Or Your variable
dgvRequests.DataBind();
}
}
3) Make controls to control the page. I used Link Buttons
<asp:LinkButton ID="lbtnPrevious" runat="server" OnClick="lbtnPrevious_Click"></asp:LinkButton>
<asp:LinkButton ID="lbtnlNext" runat="server" OnClick="lbtnlNext_Click"></asp:LinkButton>
4) On the click event, control the paging of the gridviews via the click event
protected void lbtnlNext_Click(object sender, EventArgs e)
{
dgvRequests.DataSource = GetYearData(++CurrentYear); //Or Your variable
dgvRequests.DataBind();
}
protected void lbtnPrevious_Click(object sender, EventArgs e)
{
dgvRequests.DataSource = GetYearData(--CurrentYear); //Or Your variable
dgvRequests.DataBind();
}
That should allow you to "Page" in essence by using controls instead of the paging feature.
** The GetYearData function is your function in which you grab your data from
** You may also want to display the current year of data your are displaying
Related
I am adding two links and some plain text in same cell of gridview, I also have gridview_SelectedIndexChanged function which is called when any of the link is clicked and based of the value from grid I am running my db queries. gridview is also created dynamically so can have different number of rows.
Is there a way to know Link1 or Link2 is clicked in gridview_SelectedIndexChanged function?
protected void gridview_SelectedIndexChanged(object sender, EventArgs e)
{
if (Link1.Clicked)
{do this}
elseif (Link2.Clicked)
{do this}
}
You would want to track which link is clicked by using an ASP.NET control
<asp:LinkButton ID="Link1" runat="server" Click="Link1_Click" />
in your html
Then add an event handler in your backend like
public void Link1_Click(object sender, EventArgs e)
{
//add variable marking this link was clicked
link1_clicked = true;
Response.Redirect("Link1Destination.aspx");
}
and do the same for link2
<asp:LinkButton ID="Link2" runat="server" Click="Link2_Click" />
public void Link2_Click(object sender, EventArgs e)
{
//add variable marking this link was clicked
link2_clicked = true;
Response.Redirect("Link2Destination.aspx");
}
Add the boolean variables link1_clicked and link2_clicked to the top of you backend code. Then when you need to check what has been clicked you can filter though your boolean variables to see what is marked true as clicked with a for-loop.
Basically the Event handlers are your if clicked statements.
I have a radio button list whose items I need to add on Page_Load
aspx code
<asp:radioButtonList ID="radio1" runat="server" RepeatLayout="Flow" RepeatDirection="Horizontal">
</asp:radioButtonList>
code behind
protected void Page_Load(object sender, EventArgs e)
{
RadioButtonList radioList = (RadioButtonList)Page.FindControl("radio1");
radioList.Items.Add(new ListItem("Apple", "1"));
}
After the control reaches radioList.Items.Add
I keep getting the Object reference not set to instance of an object
error
What am I doing wrong?
You don't need to to do a FindCOntrol. As you used the runat="server" attributes, just get the reference of your RadioList via its name "radio1"
protected void Page_Load(object sender, EventArgs e)
{
radio1.Items.Add(new ListItem("Apple", "1"));
}
By using
RadioButtonList radioList = (RadioButtonList)Page.FindControl("radio1");
radioList.Items.Add(new ListItem("Apple", "1"));
you are not adding your list on the control on your page, but on an un-instanciated Radiobuttonlist called radioList.
If the page is reachable from the class, use
radio1.Items.Add(new ListItem("Apple", "1"));
you must add !ispostback
if (!IsPostBack)
{
radio1.Items.Add(new ListItem("Apple", "1"));
}
As an alternative to using the < asp: **> tools -
I needed to reuse a radio option which relies on a lot of jQuery integration in the site. (Also wanted to avoid just CSS hiding the content within the html code of the aspx page.)
The radio buttons needed only appear in an 'edit' page depending on security ACU level logic within the codebehind and rendered with currently stored item value data found in the db.
So I used the following:
string RadioOnChk1 = (db.fieldChecked == true) ? "checked='checked'" : "";
string RadioOnChk2 = (db.fieldChecked == false) ? "checked='checked'" : "";
if (ACU > 3)
{
// Create radio buttons with pre-checked
StringBuilder RadioButtns = new StringBuilder(); // Form input values
{
RadioButtns.Append("<p><label><input type=\"radio\" id=\"radiocomm1\" name=\"custmComm\" value=\"1\"");
RadioButtns.Append(RateIncChk1 + "/>Included or </label>");
RadioButtns.Append("<label><input type=\"radio\" id=\"radiocomm2\" name=\"custmComm\" value=\"2\"");
RadioButtns.Append(RateIncChk2 + "/>Excluded</label>");
RadioButtns.Append("</p>");
}
htmlVariable = (RadioButtns.ToString());
}
It works.. Is this a wrong way of going about it?
I'm having a hard time figuring this out and I hope you guys would help me.
I have a page called Index.aspx with a DropDownList that is a separate UserControl class (because it will be used in other pages). Here's the code for that:
UcSelecionarLocal.ascx:
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="UcSelecionarLocal.ascx.cs"
Inherits="QuickMassage.uc.UcSelecionarLocal" %>
<asp:DropDownList ID="ddlLocais" runat="server"
CssClass="span4 dropdown-toggle" AutoPostBack="true">
</asp:DropDownList>
UcSelecionarLocal.ascx.cs:
public partial class UcSelecionarLocal : UserControl {
protected void Page_Load(object sender, EventArgs e) {
if (!this.IsPostBack) {
PreencherLocais();
}
}
private void PreencherLocais() {
ddlLocais.Items.Clear();
ddlLocais.Items.Add(new ListItem("Selecione", "0"));
ControleLocal controle = new ControleLocal();
DataTable tab = controle.ListarLocais();
foreach (DataRow row in tab.Rows) {
ddlLocais.Items.Add(new ListItem(row["Descricao"].ToString(),
row["ID"].ToString()));
}
}
}
This control is placed in Index.aspx and loads its values correctly. The form that it's contained in, has the action set to agendamentos.aspx. When I change the ddlist, the page is submitted to the forms action page, as it should be.
On the other page the problems begin: I get the parameters posted to this page and one of them is the ddlist value. In the immediate window, I check the value and it's there, let's say that it is 1.
To make long story short, I have this code:
agendamentos.aspx.cs:
protected void Page_Load(object sender, EventArgs e) {
DropDownList locais = ObterComponenteListaLocais();
try {
locais.SelectedIndex =
int.Parse(HttpContext.Current.Request["ucSelLocal$ddlLocais"]);
}
While debugging, I see that locais.SelectedIndex is -1. After the assignment it remains -1. The page loads and then I change the ddlist value again to 2. When debugging the same code above, I see that the locais.SelectedIndex is now 1. Again, setting it to 2, as it would normally be, produces no effect. If I change the ddlist again to 3, the SelectedIndex becomes 2 and does not take the value 3.
In other words: the value of the index in a newly loaded page is the value of the page that was loaded before.
Could you guys help me?
This is because the Page_Load event is firing in your page before the user control is loading. Do this:
public partial class UcSelecionarLocal : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void PreencherLocais()
{
ddlLocais.Items.Clear();
ddlLocais.Items.Add(new ListItem("Selecione", "0"));
ControleLocal controle = new ControleLocal();
DataTable tab = controle.ListarLocais();
foreach (DataRow row in tab.Rows)
{
ddlLocais.Items.Add(new ListItem(row["Descricao"].ToString(), row["ID"].ToString()));
}
}
}
Then in your aspx page:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
this.idOfYourUserControl.PreencherLocais();
DropDownList locais = ObterComponenteListaLocais();
try {
locais.SelectedIndex =
int.Parse(HttpContext.Current.Request["ucSelLocal$ddlLocais"]);
}
}
Also because your question is a little confusing, an important note is that Page_Load fires before data is captured from controls that post back data. So that's a bad place to get their information because it will be what it was previously. That's why you need to create a function that fires on something like a button click that will execute after the controls data have been loaded.
I am dynamically adding a custom user control to an update panel. My user control contains two dropdownlists and a textbox. When a control outside of the update panel triggers a postsback, I am re-adding the user control to the update panel.
The problem is...on postback when I re-add the user controls, it's firing the "SelectedIndexChanged" event of the dropdownlists inside the user control. Even if the selectedindex did not change since the last postback.
Any ideas?
I can post the code if necessary, but there's quite a bit in this particular scenario.
Thanks in advance!
EDIT...CODE ADDED BELOW
*.ASCX
<asp:DropDownList ID="ddlColumns" OnSelectedIndexChanged="ddlColumns_SelectedChanged" AppendDataBoundItems="true" AutoPostBack="true" runat="server">
*.ASCX.CS
List<dataColumnSpecs> dataColumns = new List<dataColumnSpecs>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
fillDDLColumns();
}
}
public void fillDataColumnsList()
{
dataColumns.Clear();
//COMMON GETDATATABLE RETURNS A DATA TABLE POPULATED WITH THE RESULTS FROM THE STORED PROC COMMAND
DataTable dt = common.getDataTable(storedProcs.SELECT_COLUMNS, new List<SqlParameter>());
foreach (DataRow dr in dt.Rows)
{
dataColumns.Add(new dataColumnSpecs(dr["columnName"].ToString(), dr["friendlyName"].ToString(), dr["dataType"].ToString(), (int)dr["dataSize"]));
}
}
public void fillDDLColumns()
{
fillDataColumnsList();
ddlColumns.Items.Clear();
foreach (dataColumnSpecs dcs in dataColumns)
{
ListItem li = new ListItem();
li.Text = dcs.friendlyName;
li.Value = dcs.columnName;
ddlColumns.Items.Add(li);
}
ddlColumns.Items.Insert(0, new ListItem(" -SELECT A COLUMN- ", ""));
ddlColumns.DataBind();
}
protected void ddlColumns_SelectedChanged(object sender, EventArgs e)
{
//THIS CODE IS BEING FIRED WHEN A BUTTON ON THE PARENT *.ASPX IS CLICKED
}
*.ASPX
<asp:UpdatePanel ID="upControls" runat="server">
<ContentTemplate>
<asp:Button ID="btnAddControl" runat="server" Text="+" OnClick="btnAddControl_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID="btnGo" runat="server" Text="Go" OnClick="btnGo_Click" ValidationGroup="vgGo" />
<asp:GridView...
*.ASPX.CS
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
uc_Counter = 0;
addControl();
gridview_DataBind();
}
else
{
reloadControls();
}
}
protected void btnGo_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
//THIS BUTTON CLICK IS WHAT'S TRIGGERING THE
//SELECTEDINDEXCHANGED EVENT TO FIRE ON MY *.ASCX
gridview_DataBind();
}
}
private void reloadControls()
{
int count = this.uc_Counter;
for (int i = 0; i < count; i++)
{
Control myUserControl = Page.LoadControl("~/Controls/myUserControl.ascx");
myUserControl.ID = "scID_" + i;
upControls.ContentTemplateContainer.Controls.AddAt(i, myUserControl);
((customUserControl)myUserControl).fillDDLColumns();
}
}
private void addControl()
{
Control myUserControl = Page.LoadControl("~/Controls/myUserControl.ascx");
myUserControl.ID = "scID_" + uc_Counter.ToString();
upControls.ContentTemplateContainer.Controls.AddAt(upControls.ContentTemplateContainer.Controls.IndexOf(btnAddControl), myUserControl);
//((customUserControl)myUserControl).fillDDLColumns();
this.uc_Counter++;
}
protected int uc_Counter
{
get { return (int)ViewState["uc_Counter"]; }
set { ViewState["uc_Counter"] = value; }
}
Even though this is already answered I want to put an answer here since I've recently tangled with this problem and I couldn't find an answer anywhere that helped me but I did find a solution after a lot of digging into the code.
For me, the reason why this was happening was due to someone overwriting PageStatePersister to change how the viewstate hidden field is rendered. Why do that? I found my answer here.
One of the greatest problems when trying to optimize an ASP.NET page to be more search engine friendly is the view state hidden field. Most search engines give more score to the content of the firsts[sic] thousands of bytes of the document so if your first 2 KB are view state junk your pages are penalized. So the goal here is to move the view state data as down as possible.
What the code I encountered did was blank out the __VIEWSTATE hidden fields and create a view_state hidden field towards the bottom of the page. The problem with this is that it totally mucked up the viewstate and I was getting dropdownlists reported as being changed when they weren't, as well as having all dropdownlists going through the same handler on submit. It was a mess. My solution was to turn off this custom persister on this page only so I wouldn't have to compensate for all this weirdness.
protected override PageStatePersister PageStatePersister
{
get
{
if (LoginRedirectUrl == "/the_page_in_question.aspx")
{
return new HiddenFieldPageStatePersister(Page);
}
return new CustomPageStatePersister(this);
}
}
This allowed me to have my proper viewstate for the page I needed it on but kept the SEO code for the rest of the site. Hope this helps someone.
I found my answer in this post .net DropDownList gets cleared after postback
I changed my counter that I was storing in the viewstate to a session variable.
Then I moved my reloadControls() function from the Page_Load of the *.ASPX to the Page_Init.
The key was dynamically adding my user control in the Page_Init so it would be a member of the page before the Viewstate was applied to controls on the page.
I have a datagrid where a row can be deleted (using ajax). I'm have problem with the pager in the following scenario:
Lets say my PageSize is 10, I have 101 rows so that's 11 pages with the last page with an single element. Let no assume that I'm on page 10 (PageIndex=9) and delete a row. Then I go to the 11'th page (who's now empty and doesn't really exist). ASP now shows me the EmptyDataTemplate and no pager so I can't go back.
My approach (which isn't working) is to detect this scenario and step one page back:
public void Bind()
{
gridMain.DataBind();
}
public void SetPage(int page)
{
gridMain.PageIndex = page;
gridMain.DataBind();
}
protected void ldsGridMain_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
selectArgs = e;
e.Result = (new EnquiryListController()).GetEnquiryList(OnBind(this), supplier);
}
protected void ldsGridMain_Selected(object sender, LinqDataSourceStatusEventArgs e)
{
totalRows = selectArgs.Arguments.TotalRowCount;
//Detect if we need to update the page:
if (gridMain.PageIndex > 0 && (gridMain.PageSize * gridMain.PageIndex + 1) > totalRows) SetPage(gridMain.PageIndex - 1);
}
protected void gridMain_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
SetPage(e.NewPageIndex);
}
I can see that SetPage is called with the the right page index, but the databind doesn't seem to called as I still get the EmptyDataTemplate.
When you delete the item, you need to rebind the data, so that the pager resizes.
Not just call databind, you have to reset the datasource and call databind. It doesn't keep the data in the datasource between post backs.
Before you do that, make sure you reset the pageIndex to one that is in scope on the new set.
SetPage(gridMain.PageIndex - 1) might be incorrect. You have to calculate what the last page will be for the current row count. Current PageIndex-1 can be out of range.
Rebind the grid in SetPage with updated datasource and set pageindex. check if RecordCount/PageSize is less than NumberofPages in pager or current Page index then decrease the page index as per RecordCount/PageSize .
Can't you just use something like:
public void SetPage(int page)
{
gridMain.PageIndex = Math.Max(page, gridMain.PageCount);
gridMain.DataBind();
}