Paging ObjectDataSource - asp.net

My ASP page code:
<asp:ObjectDataSource runat="server" ID="odsResults" OnSelecting="odsResults_Selecting" />
<tr><td>
<wssawc:SPGridViewPager ID="sgvpPagerTop" runat="server" GridViewId="sgvConversionResults" />
</td></tr>
<tr>
<td colspan="2" class="ms-vb">
<wssawc:SPGridView
runat="server"
ID="sgvConversionResults"
AutoGenerateColumns="false"
RowStyle-CssClass=""
AlternatingRowStyle-CssClass="ms-alternating"
/>
</td>
</tr>
Class code:
public partial class Convert : System.Web.UI.Page
{
...
private DataTable resultDataSource = new DataTable();
...
protected void Page_Init(object sender, EventArgs e)
{
...
resultDataSource.Columns.Add("Column1");
resultDataSource.Columns.Add("Column2");
resultDataSource.Columns.Add("Column3");
resultDataSource.Columns.Add("Column4");
...
odsResults.TypeName = GetType().AssemblyQualifiedName;
odsResults.SelectMethod = "SelectData";
odsResults.SelectCountMethod = "GetRecordCount";
odsResults.EnablePaging = true;
sgvConversionResults.DataSourceID = odsResults.ID;
ConversionResultsCreateColumns();
sgvConversionResults.AllowPaging = true;
...
}
protected void btnBTN_Click(object sender, EventArgs e)
{
// add rows into resultDataSource
}
public DataTable SelectData(DataTable ds,int startRowIndex,int maximumRows)
{
DataTable dt = new DataTable();
dt.Columns.Add("Column1");
dt.Columns.Add("Column2");
dt.Columns.Add("Column3");
dt.Columns.Add("Column4");
for (int i =startRowIndex; i<startRowIndex+10 ;i++)
{
if (i<ds.Rows.Count)
{
dt.Rows.Add(ds.Rows[i][0].ToString(), ds.Rows[i][1].ToString(),
ds.Rows[i][2].ToString(), ds.Rows[i][3].ToString());
}
}
return dt;
}
public int GetRecordCount(DataTable ds)
{
return ds.Rows.Count;
}
protected void odsResults_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
e.InputParameters["ds"] = resultDataSource;
}
}
On clicking the button resultDataSource receives some rows. Page reload and we can see result in sgvConversionResults. First 10 rows. But after click next page in pager we have message "There are no items to show in this view". When I try debug I find that after postBack page (on click next page) input params "ds" is blank, ds.Rows.Count = 0 and etc... As though resultDataSource became empty((
What did I do incorrectly?
onPostBack all variables get default values, sgvConversionResults save her structure but has clear rows. How I can save sgvConversionResults data onPostBack event???

Maybe try:
protected void Page_Load(object sender, EventArgs e)
{
sgvConversionResults.DataBind();
}
Your code seems a bit convoluted though, any particular reason you are using an ObjectDataSource? Cause you can bind the datatable directly to the gridview in the codebehind

I transmit resultDataSource with ViewState and this work success!

Related

Repeater with dynamic UC

I have a formular with dynamic data and UC.
my ascx file looks like:
<asp:Repeater ID="rMyData" runat="server" OnItemDataBound="OnRepeaterItemDataBound">
<ItemTemplate>
<asp:Panel ID="panelAdditional" runat="server"/>
</ItemTemplate>
</asp:Repeater>
and the cs file:
public partial class MyFormular
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
PrepareList();
DataBind();
}
}
private void PrepareList()
{
rMyData.DataSource = GetData();
rMyData.DataBind();
}
protected void OnRepeaterItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem repeaterItem = e.Item;
Panel panel = (Panel)repeaterItem.FindControl("panelAdditional");
if (panel != null)
{
var datarow= (Data)repeaterItem.DataItem;
if (datarow!= null)
{
panel.Controls.Clear();
MyUC ctrl;
ctrl = (MyUC)Page.LoadControl("~/MyUC.ascx");
ctrl.Enabled = true;
ctrl.DataRow = datarow;
panel.Controls.Add(ctrl);
}
}
}
protected void SaveNewsletterSubscription(object sender, EventArgs e)
{
...
}
}
My problem is, it doesn't show my UC.
If I put my PrepareList() and DataBind() outside of the PostBack, it works perfectly fine and shows my UC. But after I press the save Button, it reloads the page and rebind my repeater. So I lost everything in the UC.
Why does it only show my UC if I rebind it in every pageload?
I hope the I posted enough information.

List of controls in code behind

How can I add to a list<> some controls of my dashboard? I do something like List<String> NewList = new List<Strings>(){} but this throw me errors
I'm trying to add some linkButtons into the list.
I'm tying to do something like this but is wrong
protected void listLink(){
List<LinkButton> linksList = new List<LinkButton>();
listLink{
}
}
I want to use that list in other events
my linkbuttons are in visible = false;
From what i understand you want to create a list of LinkButtons using Object Initialization way.
Below code snippet should help you.
Aspx code:
<form id="form1" runat="server">
<asp:LinkButton ID="lnkBtn1" runat="server"></asp:LinkButton>
<asp:LinkButton ID="lnkBtn2" runat="server"></asp:LinkButton>
</form>
Aspx.cs code:
List<LinkButton> lnkBtnCollection = null;
protected void Page_Init(object sender, EventArgs e)
{
//Object Initialization way
lnkBtnCollection = new List<LinkButton>
{
lnkBtn1, lnkBtn2
};
//Second way where items are added to the list after the list is created
//lnkBtnCollection = new List<LinkButton>();
//lnkBtnCollection.Add(lnkBtn1);
//lnkBtnCollection.Add(lnkBtn2);
}
protected void Page_Load(object sender, EventArgs e)
{
//Use LinkBtn Collection here
foreach (var lnkBtn in lnkBtnCollection)
{
}
}

CheckBox on a GridView

I have a grid view that has 3 columns(Name, Address, Status) and a checkbox.The Status has 3 properties, Active, Pending, and Disabled. The page load all the information from the database. When loading the page, only accounts that are ACTIVE should be displayed (and the checkbox should remain unchecked)
When clicking the checkbox, the page should load the DISABLED, along with the accounts already displayed When the page loads for the first time.
Aspx:
<asp:CheckBox ID="ChkBox1" runat="server" AutoPostBack="true" OnCheckedChanged="cbShowAllColumn_Changed" TextAlign="Right" Text="Show All"/>
</asp:Panel>
Code behind:
protected void cbShowColumn_Changed(object sender, EventArgs e)
{
string columnName = (sender as CheckBox).ID.Substring(1);
gvTest.Columns[(int)Enum.Parse(typeof(AccountColumns), columnName)].Visible = (sender as CheckBox).Checked;
}
protected void cbShowAllColumn_Changed(object sender, EventArgs e)
{
bool _checked = (sender as CheckBox).Checked;
foreach (Control ctrl in pAccount.Controls)
if (ctrl is CheckBox)
{
(ctrl as CheckBox).Checked = _checked;
gvMain.Columns[(int)Enum.Parse(typeof(AccountColumns), (ctrl as CheckBox).ID.Substring(2))].Visible = _checked;
}
}
I compiled a small asp .net page to do what you asked.
Note: In your project, you should probably take the "source" out of the BindGrid method, so that you don't "get" the data from scratch every time the page is posted back to. I did it that way because I used an anonymous type.
Note #2 I converted an int to your enum and then to a string. Since you use real data you should handle that differently, by using the enum itself.
Markup:
<asp:CheckBox ID="ChkBox1" runat="server" AutoPostBack="true" OnCheckedChanged="cbShowAllColumn_Changed" TextAlign="Right" Text="Show All"/>
<br/>
<asp:gridview ID="gvMain" runat="server" >
</asp:gridview>
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
BindGrid(false);
}
private void BindGrid(bool showActiveOnly)
{
var source = Enumerable.Range(1, 10)
.Select(number => new { number, status = (Enum.ToObject(typeof(Statuses), number % 3)).ToString() });
var filteredSource = source.Where(x => x.status == "Active" || !showActiveOnly);
gvMain.DataSource = filteredSource;
gvMain.DataBind();
}
protected void cbShowAllColumn_Changed(object sender, EventArgs e)
{
bool _checked = (sender as CheckBox).Checked;
BindGrid(_checked);
}
private enum Statuses
{
Active,
Pending,
Disabled
}

Radio button doesn't get selected after a post back

I have an item template within repeater:
<ItemTemplate>
<li>
<input type="radio"
value="<%# GetAssetId((Guid) (Container.DataItem)) %>"
name="AssetId"
<%# SelectAsset((Guid) Container.DataItem) %> />
</li>
</ItemTemplate>
I have a method that compares ids and decides whether to check the radio button.
protected string SelectAsset(Guid uniqueId)
{
if (uniqueId == GetSomeId())
return "checked=\"checked\"";
return string.Empty;
}
SelectAsset gets hit, but it doesn't select a radio button on a post back, but it does work if I just refresh the page. What am I doing wrong here?
Answer here: How to display "selected radio button" after refresh? says that it's not possible to achieve, is this really the case?
Thank you
Update
It appears that view state isn't available for simple controls if they don't have a runat attribute. I have solved this by using a custom GroupRadioButton control. Thank you for your help.
I'd suggest using a RadioButtonList:
Page Code
<asp:RadioButtonList RepeatLayout="UnorderedList" OnSelectedIndexChanged="IndexChanged" AutoPostBack="true" ID="RadioRepeater" runat="server" />
<asp:Label ID="SelectedRadioLabel" runat="server" />
Code Behind
if (!Page.IsPostBack)
{
/* example adds items manually
- you could iterate your datasource here as well */
this.RadioRepeater.Items.Add(new ListItem("Foo"));
this.RadioRepeater.Items.Add(new ListItem("Bar"));
this.RadioRepeater.Items.Add(new ListItem("Baz"));
this.RadioRepeater.SelectedIndex = this.RadioRepeater.Items.IndexOf(new ListItem("Bar"));
this.RadioRepeater.DataBind();
}
protected void IndexChanged(object sender, EventArgs e)
{
this.SelectedRadioLabel.Text = string.Format("Selected Item Text: {0}", this.RadioRepeater.SelectedItem.Text);
}
I assume you only need to select one item.
As described in the comments, it even works to access the SelectedItem in the Page_Loadevent handler:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// previous code omitted
}
else
{
string foo = this.RadioRepeater.SelectedItem.Text;
}
}
If you are creating all your controls dynamically at run-time (directly from code), then things are a little different. Here is the code that I used:
Page Code
<form id="form1" runat="server">
</form>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
RadioButtonList rbl = new RadioButtonList();
rbl.AutoPostBack = true;
rbl.SelectedIndexChanged += rbl_SelectedIndexChanged;
rbl.Items.Add("All");
// generate your dynamic radio buttons here
for (int i = 0; i<5; i++)
{
rbl.Items.Add(string.Format("Dynamic{0}", i));
}
form1.Controls.Add(rbl);
if (!Page.IsPostBack)
{
rbl.SelectedValue = "All";
PopulateTextBox(rbl.SelectedValue);
}
}
void rbl_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList foo = (RadioButtonList)sender;
PopulateTextBox(foo.SelectedValue);
}
void PopulateTextBox(string selection)
{
TextBox box = new TextBox();
box.Text = selection;
form1.Controls.Add(box);
}

asp.net web forms best practice to retrieve dynamic server control values

I populate web form with dynamic list of exams from database. I want user to enter examination marks for each exam. There is list of exam titles and textbox near each title.
I create list with repeater control (ViewState is disabled) :
<asp:Repeater ID="rptExams" runat="server" onitemdatabound="rptExams_ItemDataBound" >
<ItemTemplate>
<tr>
<td>
<asp:Literal runat="server" ID="ltTitle"/>
</td>
<td>
<asp:HiddenField runat="server" ID="hfId"/>
<asp:Textbox runat="server" ID="tbMark"/>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
And bind data to repeater on page_init:
class Exam
{
public int Id { get; set;}
public string Title { get; set;}
}
...
// this list is retrieved from database actually
Exam[] Exams = new Exam[]
{
new Exam { Id = 1, Title = "Math"},
new Exam { Id = 2, Title = "History"}
};
...
protected void Page_Init(object sender, EventArgs e)
{
rptExams.DataSource = Exams;
rptExams.DataBind();
}
So far so good. Then I have to retrieve data on postback. I have two ways but both of them looks ugly.
Idea is to store dynamically created databounded controls on ItemDataBoundEvent in Page_Init stage, and process their values in Page_Load stage. It looks like this:
private Dictionary<HiddenField, TextBox> Id2Mark = new Dictionary<HiddenField, TextBox>();
protected void rptExams_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
...
if (IsPostBack)
{
var tbMark = (TextBox)e.Item.FindControl("tbMark");
var hfId = (HiddenField)e.Item.FindControl("hfId");
// store dynamically created controls
Id2Mark.Add(hfId, tbMark);
}
...
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
foreach (var pair in Id2Mark)
{
int examId = Int32.Parse(pair.Key.Value);
string mark = pair.Value.Text;
// PROCESS
}
...
I'm completely sure there is a better way to retrieve data from dynamically created controls. Thank you in advance!
Here's how you can do it:
First, don't rebind the data on postback - it's not necessary. Only bind it on the first call of the page.
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack){
rptExams.DataSource = Exams;
rptExams.DataBind();
}
}
You won't need the Dictionary neither.
Then, on a postback, you can get to the bound data as follows:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
foreach (RepeaterItem item in rptExams.Items)
{
HiddenField hfId = item.FindControl("hfId") as HiddenField;
TextBox tbMark = item.FindControl("tbMark") as TextBox;
int examId = Int32.Parse(hfId);
string mark = tbMark.Text;
// PROCESS
}
}
}

Resources