how to add sorting function in repeater in asp 2.0? - asp.net

I m using asp 2.0, I need an requirement for sorting the repeater control. I search over the Internet but i could nt find the correct solution. If anyone knows the answer please help to solve my problem.

You need to sort the collection before binding to the repeater.
If you want to dynamically sort on post backs, sort in the event handler before re-binding to the repeater.

This article explains how to add sort functionality to a Repeater or a DataList control. It might help to your purpose or at least as a guide.

Finally i got the Sorting output in Repeater Control.
1.Maintaining the Static Variable;
static int count = 0;
2.In LinkButton click Event
protected void lnkreq_name_click(object sender, EventArgs e)
{
count=Convert.ToInt32(ViewState["count"].ToString());
ViewState["count"] = count;
loadRepeater("REQUEST_NAME",count);
}
3.call the Function
protected void loadRepeater(string reqname,int count)
{
//write the code to bind into Dataset
DataView dv = ds.Tables[0].DefaultView;
if (count == 0)
{
dv.Sort = reqname + " asc";
ViewState["count"] = 1;
}
else if (count == 1)
{
dv.Sort = reqname + " desc";
ViewState["count"] = 0;
}
//then bind into repeater
}
4.In Repeater
<asp:Repeater runat="server" ID="RepeaterEntry" >
<HeaderTemplate >
<table class="list_table" border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<th><asp:LinkButton ID="lnkreq_name" runat="server" ForeColor="white" OnClick="lnkreq_name_click" >Request Name</asp:LinkButton></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("REQUEST_NAME")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>

Related

wont display drop down

<form>
<asp:Repeater id="rptComments" runat="server">
<HeaderTemplate>
<table class="detailstable FadeOutOnEdit">
<tr>
<th style="width:200px;">Answers</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<th style="width:200px;"><asp:DropDownList ID="dropDownForChecklistAnswers" runat="server" /></th>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
<asp:Button id="button" text="Submit" OnClick="Page_Load" runat="server" />
</FooterTemplate>
</asp:Repeater>
</form>
Code Behind:
List<Checklist_Record_Choice> CLRC =
(from choice in db.Checklist_Record_Choices
select choice).ToList();
dropDownForChecklistAnswers.DataSource = CLRC;
DropDownList1.DataTextField = Text;//Text being the name of column2 in the table (which contains yes, no, n/a)
dropDownForChecklistAnswers.DataBind();
ERROR: dropDownForChecklistAnswers does not exist in the current context???
please advise
EDIT;
thanks for reply. I have
public void OnReptDataBound(object sender, RepeaterItemEventArgs e)
{
ClarkeDBDataContext db1 = new ClarkeDBDataContext();
List<string> CLRC =
(from choice in db1.Checklist_Record_Choices
select choice.Text).ToList();
DropDownList ddl = (DropDownList)e.Item.FindControl("dropDownForChecklistAnswers");
ddl.DataSource = CLRC;
}
but DropDownList ddl is coming back as object ref not set to instance of an object...why is it null??
You need to use FindControl to access a control which is part of a Repeater's template.
Subscribe to the OnItemDataBound of the Repeater (set the attribute OnItemDataBound="OnReptDataBound")
And then in your code behind do the following
void OnReptDataBound(object sender, RepeaterItemEventArgs e)
{
if(e.Item.ItemType == ListItemType.Item)
{
DropDownList ddl = (DropDownList )e.Item.FindControl("dropDownForChecklistAnswers");
ddl.DataSource = ....

ListView find dropdownlist in table

I have a list view with table inside and i need to get all dropdown lists and file upload controls, but find returns nothing. This is my code:
<asp:ListView runat="server" ID="MyListView" OnItemDataBound="FillDropDownList">
<LayoutTemplate>
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<th>Wholesaler</th>
<th>Import</th>
<th>Period</th>
<th>Upload Date</th>
<th>Upload</th>
</tr>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr class="row1">
<td><%# DataBinder.Eval(Container.DataItem, "Wholesaler") %></td>
<td><%# DataBinder.Eval(Container.DataItem, "Import")%></td>
<td><%# DataBinder.Eval(Container.DataItem, "Period")%></td>
<td><asp:DropDownList runat="server" ID="DaysDropDownList"></asp:DropDownList></td>
<td><asp:FileUpload ID="FileUpload" runat="server" /></td>
</tr>
</ItemTemplate>
</asp:ListView>
DropDownList dr = (DropDownList)MyListView.Controls[0].FindControl("DaysDropDownList");
FileUpload fl = (FileUpload)MyListView.Controls[0].FindControl("FileUpload");
figured...and you got that error, because the listview was not binded yet, so i think the best way would be to do all this on the ItemDataBound event. You would find the dropdownlist like:
protected void FillDropdownlist(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
DropDownList dr = (DropDownList)e.Item.FindControl("DaysDropDownList");
FileUpload fl = (FileUpload)e.Item.FindControl("FileUpload");
if (dr!= null)
{
//code here
}
}
}
You need to iterate over the Items collection of the listview, and then use FindControl on each item. Something like this should put you on the right track:
foreach (var lvItem in MyListView.Items)
{
if (lvItem.ItemType == ListViewItemType.DataItem)
{
DropDownList dr = (DropDownList)lvItem.FindControl("DaysDropDownList");
FileUpload fl = (FileUpload)lvItem.FindControl("FileUpload");
}
}
That's because MyListView.Controls[0] points to an inner control that does not contain those two.
Try debugging and finding precisely which is your container control, and then accessing it directly without a hard coded index. It's accessible via the event parameter of your row binding calls.
Also might I suggest you use the as operator as it doesn't raise an exception:
The as operator is like a cast except that it yields null on conversion failure instead of raising an exception
i.e.
DropDownList dr = e.Item.FindControl("DaysDropDownList") as DropDownList;
FileUpload fl = e.Item.FindControl("FileUpload") as FileUpload;
or after it's bound
//Loop i for the items of your listview
DropDownList dr = MyListView.Items[i].FindControl("DaysDropDownList") as DropDownList;
FileUpload fl = MyListView.Items[i].FindControl("FileUpload") as FileUpload;

asp.net ListView Sorting using DataBind

Sort listview using column headings in the LayoutTemplate
I am able to sort a basic list view using asp:SqlDataSource and setting the list view property DataSourceID by pointing it to the asp:SqlDataSource ID. I am having an issue when sorting when not using the asp:SqlDataSource and just DataBinding from the code behind.
SqlDataSource Example:
<asp:ListView ID="ContactsListView" DataSourceID="ContactsDataSource" runat="server">
<LayoutTemplate>
<table width="640px" runat="server">
<tr class="header" align="center" runat="server">
<td>
<asp:LinkButton runat="server" ID="SortByFirstNameButton" CommandName="Sort" Text="First Name" CommandArgument="FirstName" />
</LayoutTemplate>
....
</asp:ListView>
<asp:SqlDataSource ID="ContactsDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:MainConnString %>"
SelectCommand="SELECT * FROM TableName">
</asp:SqlDataSource>
DataBind Example:
<asp:ListView ID="ContactsListView" DataSourceID="ContactsDataSource" runat="server">
<LayoutTemplate>
<table width="640px" runat="server">
<tr class="header" align="center" runat="server">
<td>
<asp:LinkButton runat="server" ID="SortByFirstNameButton" CommandName="Sort" Text="First Name" CommandArgument="FirstName" />
</LayoutTemplate>
....
</asp:ListView>
protected void Page_Load(object sender, EventArgs e)
{
String SQL = "SELECT * FROM Customer";
SqlDataAdapter da= new SqlDataAdapter(SQL, ConnStr);
DataSet ds = new DataSet();
da.Fill(ds);
ContactsListView.DataSource = ds.Tables[0];
ContactsListView.DataBind();
}
Both code samples populate the list view, but the second example data binding does not work for sorting. With the first example, the sorting just works with the added asp:LinkButton in the LayoutTemplate adding the CommandName="sort" and setting the CommandArugment="ColumnName", but it does not work with the second example.
Can anyone please explain why and how to get the sorting working using the code behind DataBind method?
Thanks!
I solved my issue.
I added an event to handle the sorting. The event grabs the command name (Data column) and passes it and the sorting direction into a function which will make another call to the database sort the returned results and rebind to the List View.
I had to create a view state to hold the List View Sort Direction because for some reason, the onsorting event handler kept saying that the sort direction was ascending.
Front End
<asp:ListView ID="ContactsListView" OnSorting="ContactsListView_Sorting" runat="server">
<LayoutTemplate>
<table width="640px" runat="server">
<tr class="header" align="center" runat="server">
<td>
<asp:LinkButton runat="server" ID="SortByFirstNameButton" CommandName="Sort" Text="First Name" CommandArgument="FirstName" />
</LayoutTemplate>
....
</asp:ListView>
Back End
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
BindContacts(string.Empty);
}
}
protected SortDirection ListViewSortDirection
{
get
{
if (ViewState["sortDirection"] == null)
ViewState["sortDirection"] = SortDirection.Ascending;
return (SortDirection)ViewState["sortDirection"];
}
set { ViewState["sortDirection"] = value; }
}
protected void ContactsListView_Sorting(Object sender, ListViewSortEventArgs e)
{
BindContacts(e.SortExpression + " " + ListViewSortDirection.ToString());
// Check the sort direction to set the image URL accordingly.
string imgUrl;
if (ListViewSortDirection == SortDirection.Ascending)
ListViewSortDirection = SortDirection.Descending;
else
ListViewSortDirection = SortDirection.Ascending;
}
private void BindContacts(string sortExpression)
{
sortExpression = sortExpression.Replace("Ascending", "ASC");
sortExpression = sortExpression.Replace("Descending", "DESC");
using (SqlConnection conn = new SqlConnection(_connStr))
{
conn.Open();
using (SqlDataAdapter dAd = new SqlDataAdapter("SELECT * FROM Customer", conn))
{
DataTable dTable = new DataTable();
dAd.Fill(dTable);
// Sort now
dTable.DefaultView.Sort = sortExpression;
// Bind data now
ContactsListView.DataSource = dTable;
ContactsListView.DataBind();
}
conn.Close();
}
}
I guess you could try to add a handler for ListView's Sorting event. There you are given the sorting column and the sort order in the event arguments. This could be easily usable to build a specific query and bind it to the list.
Because depending on the sort expression (which you defined in your markup) SqlDataSource will very likely do something like this (I'm not sure this is exactly what it does) for you behind the scenes:
Expression<Func<DataRow,object>> myExpression = row => row["SortExpressionYouDefinedForTheColumn"];
IEnumerable<DataRow> ex = ds.Tables[0].AsEnumerable().OrderBy(myExpression.Compile());
Or SqlDataSource may be using a DataView to sort the DataTable.
SqlDataSource can do this because by default it uses a DataSet to store the result set (or so says the documentation):
The data retrieval mode identifies how a SqlDataSource control retrieves data from the underlying database.
When the DataSourceMode property is set to the DataSet value, data is
loaded into a DataSet object and stored in memory on the server. This
enables scenarios where user interface controls, such as GridView,
offer sorting, filtering, and paging capabilities..
Since you chose to bind manually to a DataSet, you need to do the "magic" yourself; in other words, you handle the OnSort command, get the sort expression, get your data source again (however you do it, from Session or by calling the database again) and do your sort similarly to the lines shown above and rebind to your Gridview.

clearing checkboxlist

on my save button i want to clear all values of form i did the following for CheckBoxList beach.
But it doesn't work. Why so, it doesn't make values clear for checkbox list
Branch is filled like this:
protected void course_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
int courseId = Convert.ToInt32(course.SelectedValue);
DataTable dt;
dt = placementManager.GetBranchList(courseId);
if (dt.Rows.Count != 0)
{
Branch.DataSource = dt;
Branch.DataTextField = "branch_name";
Branch.DataValueField = "branch_id";
Branch.DataBind();
}
Btnsave.Visible = false;
GridView1.Visible = false;
}
catch (Exception ex)
{
COMMON.logger.Error("Error on course_SelectedIndexChanged:CompanySelected.aspx.cs", ex);
}
if (b)
{
gridNotExist.Text = "Records Successfully inserted for the displayed table, To insert new records select new entries";
this.ViewState.Remove("selectedList");
this.ViewState.Remove("dt");
Session.Abandon();
passout.SelectedIndex = 0;
company.SelectedIndex = 0;
txtpackage.Text = "";
course.SelectedIndex = 0;
Branch.DataSource = null;
Branch.DataBind();
vistDate.Text = "";
txtvenue.Text = "";
//GridView1.Visible = true;
}
}
aspx page has, of course, branch like this:
<asp:UpdatePanel id="update" runat="server">
<contenttemplate>
<td>
<asp:DropDownList ID="course" runat="server" AutoPostBack="True" OnSelectedIndexChanged="course_SelectedIndexChanged" />
<asp:CustomValidator ID="coursenecessaryForSaveButton" runat="server" ControlToValidate="course" ErrorMessage="Select A Course" OnServerValidate="coursenecessaryForSaveButton_ServerValidate" ValidationGroup="save" />
</td>
<td>
<asp:CustomValidator ID="courseNecessary" runat="server" ErrorMessage="Select A Course" OnServerValidate="courseNecessary_ServerValidate" ValidationGroup="verify" />
</td>
<td style="width: 101px">
Branch Name*
</td>
<td style="width: 126px">
<asp:CheckBoxList id="Branch" runat="server" />
</td>
</contenttemplate>
</asp:UpdatePanel>
<asp:CheckBoxList id="Branch" runat="server" >
is in a different UpdatePanel to the control which is triggering the asynchronous postback - and firing your eventhandler: course_SelectedIndexChanged.
Put the Checkbox List inside the UpdatePanel with id="update" and it will solve your problem.
Still, i would consider refactoring your HTML (and code while you're at it).
For instance - you have two UpdatePanel's - why?
The second one has nothing in it besides checkboxes. The purpose of an UpdatePanel is to dynamically update portions of a page (ie dynamic information) without a full postback.
Having nothing but static controls (checkboxes) inside an UpdatePanel isn't really serving any purpose.
However, my above answer is a stab in the dark at what you're after. You're code-behind code does'nt really make sense:
if (b == true)
Where is b defined??
Branch.DataSource = null
Branch.DataBind()
What are you binding??

Injecting table row inside repeater item

I am trying to inject inside repeaters items, the problem is that the row is generated in a wrong location.
If you try this simple example, you will see that the rown is generated under label '2' as it should be generated under label '1'.
Why does it happen? And how to fix that?
protected void Page_Load(object sender, EventArgs e)
{
int [] array = {1,2,3,4,5};
rpt.DataSource = array;
rpt.DataBind();
}
protected string _extraRowHtml;
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
int tmp = ((int)e.Item.DataItem);
_extraRowHtml = tmp == 1 ? "<tr><td class=\"topicsRow\" colspan=\"100%\"> Topics </td></tr>" : string.Empty; ;
}
}
<asp:Repeater ID="rpt" runat="server" onitemdatabound="rpt_ItemDataBound">
<HeaderTemplate>
<table cellpadding="0px" cellspacing="0">
</HeaderTemplate>
<ItemTemplate>
<tr style="height:50px">
<td>
<asp:HyperLink ID="lnkTitle" runat="server" Text='<%# Container.DataItem%>'/>
</td>
</tr>
<%# _extraRowHtml %>
</ItemTemplate>
<FooterTempl
</table>
</FooterTemplate>
</asp:Repeater>
Personally I think a better way of doing is is to replace:
<%# _extraRowHtml %>
with
<%# GetExtraRow(Container.DataItem) %>
then in your code behind implement:
protected string GetExtraRow(object Data)
{
int tmp = (int) Data:
return _tmp == 1 ?
"<tr><td class=\"topicsRow\" colspan=\"100%\"> Topics </td></tr>" :
string.Empty;
}
Then and get rid of the rpt_ItemDataBound function (and the onItemDataBound).
Doing things this way is going to be prone to error, as using a variable in this manner is not something that you are going to have full control over.
What I would do is add something like the following to the template.
<asp:literal id="litExtraRow" runat="server" mode="Passthrough" />
Then in your codebehind on the item databound event
if (((int)e.Item.DataItem) == 1)
{
((Literal)e.Item.FindControl("litExtraRow")).Text = "Your HTML Here";
}
Something like this should be a bit more reliable.
The reason you are having issues is that the template is evaluated with the values as they are as "ItemDataBound" has been called, and row 1, the value is string.Empty, and then for the second row, you updated it after item 1 was databound.

Resources