I have a RadGrid that I supply with data using DataSourceID. The RadGrid has paging, and I want to show the page containing some particular item. To do this, I find the offset of the item in the data and set the page number:
var index = dataSource.Count(t => t.Id > _selectedTickId);
var page = index / rgTicks.PageSize;
rgTicks.CurrentPageIndex = page;
My question is where to put this code. In the OnDataBound I don't seem to have access to the data source. If I put it in the OnSelecting the retrieving of data has a side effect of setting the page number. Should I extend the GridTableView to implement this functionality? Which method should I override?
I will suggest to compute index value in OnSelecting (which is data dependent) while page index can be set in OnDataBound or PreRender event.
My usecase was to jump to an item that was just inserted using a popup editor. Here's how I solved it. I am omitting non relevant properties in the tag. All the data wiring is up to you, but here are the relevant bits. Important: use DataKeyNames to avoid messy digging in the GridDataItem for a value.
In the page I have:
<telerik:RadGrid ID="rgItems" runat="server" AllowPaging="true"
OnNeedDataSource="rgItems_NeedDataSource"
OnPreRender="rgItems_PreRender"
OnInsertCommand="rgItems_InsertCommand">
<MasterTableView
CommandItemDisplay="Top"
CommandItemSettings-AddNewRecordText="Add New Item"
CommandItemSettings-ShowAddNewRecordButton="True"
DataKeyNames="IntItemId"
EditMode="popup"
EditFormSettings-PopUpSettings-Modal="true">
And in code behind:
private bool itemInserted = false;
protected void rgItems_InsertCommand(object sender, GridCommandEventArgs e)
{
itemInserted = true;
}
protected void rgItems_PreRender(object sender, EventArgs e)
{
if (itemInserted)
{
// Select the record and set the page
int LastItem = 0; // Put code to get last inserted item here
int Pagecount = rgItems.MasterTableView.PageCount;
int i = 0;
GridDataItem GDI = null;
while (i < Pagecount)
{
rgItems.CurrentPageIndex = i;
rgItems.Rebind();
GDI = rgItems.MasterTableView.FindItemByKeyValue("IntItemId", LastItem);
if (GDI != null) break; // IMPORTANT: Breaking here if the item is found stops you on the page the item is on
i++;
}
if (GDI != null) GDI.Selected = true; // Optional: Select the item
itemInserted = false;
}
}
Related
I have a gridview. Its datasource is taken from XML by adding some xmlElemens in a list and than set the list as its data source. Now I am implementing a search feature.
So I am filtering the list in this way:
protected void btnSearch_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(prog); //Percorso file xml
List<string> nomi = new List<string>();
XmlElement root = doc.DocumentElement;
XmlNodeList elemLists = root.GetElementsByTagName("nome");
// this binds the gridview to the title text to display
for (int i = 0; i < elemLists.Count; i++)
{
if(elemLists[i].InnerXml.ToString().ToLower().StartsWith(txtSearchMaster.Text.ToLower()) ||
elemLists[i].InnerXml.ToString().ToLower() == txtSearchMaster.Text.ToLower() ||
elemLists[i].InnerXml.ToString().ToLower().EndsWith(txtSearchMaster.Text.ToLower()) ||
elemLists[i].InnerXml.ToString().ToLower().Contains(txtSearchMaster.Text.ToLower()))
nomi.Add(elemLists[i].InnerXml.ToString());
}
GridView1.DataSource = nomi.OrderBy(q => q).ToList();
GridView1.DataBind();
}
The data is shown correctly but the problem is that when I click the button next the column that is auto generated and get the cell content (that is an element of the list) it return the content of the cell at the same index but of the previous data.
How can I overcome to this?
The problem here is that your "filter" as it were is only applied on the search click. If you had hidden state where a search term was stored, and applied it on every postback, if the state exists, then clicking your grid button would work.
<asp:HiddenField ID="SearchString" runat="server" value="" />
and in your btnSearch_Click
SearchString.Value = txtSearchMaster.Text.ToLower().Trim();
and then add the filter logic in Page_Load
if (IsPostBack) {
// filter on hidden value if not empty.
if (!String.IsNullOrEmpty(SearchString.Value)) {
// filter here
}
}
Just fixed by adding
if (!IsPostBack)
{
...
}
in Page_Load and leaving the filter login into the search button click method.
I have a Telerik Radgrid. I want to disable hyperlink columns on page load event when a specific condition is true.
I get role id from the database and on the basis of role id want to disable hyperlink columns on page load event.
my code is here
if(RoleId==3)
{
btnsave.Enabled= false;
foreach(griddataitem item in RagGrid1.Items)
{
HyperLink edit = (hyperlink)item["EditHyperLinkColumn"].Controls[0];
edit.Enabled = false;
}
}
when the page loads it gets the role id but did not go inside the foreach statement.
Please help.thanks in advance...
Where did you put your foreach loop in? In Page_Load method? This may not work because RadGrid has its own life cycle and events happen in particular sequence.
What you can do instead is to apply your condition in ItemDataBound event.
protected void RadGrid1_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item is GridDataItem)
{
var item = (GridDataItem)e.Item;
var editlink = item.FindControl("EditHyperLinkColumn") as HyperLink;
if (editlink != null)
{
editlink.Enabled = false;
}
}
}
You need to get the items in the MasterTableView.
Also, verify the UniqueName of the Hyperlink Column. Is it actually "EditHyperLinkColumn"?
if(RoleID == 3)
{
btnsave.Enabled = false;
foreach(GridDataItem item in RadGrid1.MasterTableView.Items)
{
HyperLink edit = (HyperLink)item["EditHyperLinkColumn"].Controls[0];
edit.Enabled = false;
}
}
Ok so I've been working on this for like... I don't know, 5 hours? I'm pulling my hair out starting to think it's just not possible with asp.net! ugh! I've looked at all kinds of resources (I even tried implementing DynamicControlsPlaceholder that was created by someone else years ago - which failed miserably). So here's the issue in hopes someone here has a solution!
I'm trying to have a page where the user can dynamically add DropDownLists without forgetting the values they set in the previous lists. So for example, let's say the user is given 1 DropDownList and chooses index 2. There will be a button below that says "Add" and that will add another DropDownList. When doing this, however, the page does a postback and the previous DropDownList loses the value of index 2 and resets back to index 0 instead. I can't figure out how to save the state of the DropDownList before the postback is made. The point of this is so that when the user is complete, they can click "Submit" with all the values made in the DropDownLists. Here's the code I currently have (that's important) which simply regenerates the same number of DropDownLists as there's supposed to be (based on the ViewState["layoutCount"]). Naturally, I should be able to "restore" the index that was selected before a reload of the page...
aspx file:
<table style="text-align:center; width:60%;">
<asp:Panel ID="layoutAreaPanel" runat="server" CssClass="paragraphStyle" />
</table>
<asp:Button ID="cmdLayout1AddPage" runat="server" OnClick="cmdLayout1AddPage_Click" />
C#:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
CreatePanelInfo();
}
....
protected void CreatePanelInfo()
{
int layoutCount = 0;
if (ViewState["layoutCount"] != null)
layoutCount = (int)(ViewState["layoutCount"]);
for (int i = 0; i < layoutCount; i++)
{
TableRow mainRow = new TableRow();
TableCell labelCell = new TableCell();
TableCell dropDownListCell = new TableCell();
Label cellLabel = new Label();
cellLabel.Text = Language.GetLanguageText("ADDPAGE_PAGE", this.Page);
cellLabel.CssClass = "paragraphStyle";
labelCell.HorizontalAlign = HorizontalAlign.Right;
labelCell.Controls.Add(cellLabel);
DropDownList pnlDropDownList = new DropDownList();
pnlDropDownList.ID = "pnlDropDownList" + (i + 1);
pnlDropDownList.BorderWidth = 1;
pnlDropDownList.Width = new Unit("100%");
FillPageList(ref pnlDropDownList); //adds items to the list
dropDownListCell.Controls.Add(pnlDropDownList);
mainRow.Controls.Add(labelCell);
mainRow.Controls.Add(dropDownListCell);
layoutAreaPanel.Controls.Add(mainRow);
}
ViewState["layoutCount"] = layoutCount + 1;
}
....
protected void cmdLayout1AddPage_Click(object sender, EventArgs e)
{
CreatePanelInfo();
}
Hopefully that's enough information to get a good answer... :S
Only make your dropdown lists making a postback when their selected index changes.
In the code behind, store selections in Session variable.
public void AddDDL()
{
var tmp = new DropDownList();
tmp.SelectedIndexChanged += ddl_SelectedIndexChanged;
Page.Controls.Add(tmp);
}
protected void ddl_SelectedIndexChanged(object sender, EventArgs e)
{
var ddl = sender as DropDownList;
var lists = Session["dropdownlists"] as Dictionary<DropDownList, int>;
lists[ddl] = ddl.SelectedIndex;
}
and finally in postback event set the selected indices again:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostback)
{
var lists = Session["dropdownlists"] as Dictionary<DropDownList, int>;
foreach (var item in lists)
item.Key.SelectedIndex = item.Value;
}
else Session["dropdownlists"] = new Dictionary<DropDownList, int>();
}
Postback is not recommended because it is not user friendly. You should use an UpdatePanel.
I need to get a sum for all items in a column within a listview. I put in the following code in the itemdatabound event, but realized after testing it that it will only be getting what is bound, oops.
So I was looking for a little help converting this to show a total for my column from all items bound to the ListView.
Thanks.
if (e.Item.ItemType == ListViewItemType.DataItem)
{
ListViewDataItem item = (ListViewDataItem)e.Item;
Label lblQty = (Label)e.Item.FindControl("lblQuantity");
if (lblQty == null)
{
return;
}
if (lblQty.Text.Length == 0 || lblQty.Text == "")
{
return;
}
else
{
ListViewTotal += int.Parse(lblQty.Text);
}
}
The best method I have found to do this is to implement the OnDataBinding method for the control you are binding. For example:
<asp:ListView ID="ListView1" runat="server">
<ItemTemplate>
<asp:Literal ID="yourLiteral" runat="server"
OnDataBinding="yourLiteral_DataBinding"></asp:Literal>
</ItemTemplate>
</asp:ListView>
First define a global counter in your .cs:
private int _quantityTotal = 0;
Then implement the OnDataBinding for the control:
protected void yourLiteral_DataBinding(object sender, System.EventArgs e)
{
// You could get anything here to get a value including calling a DB
// call if you want for each item that is being bound.
Literal lt = (Literal)(sender);
int quantity = (int)(Eval("yourQuantityField"));
_quantityTotal += quantity;
lt.Text = quantity.ToString();
}
Now you have the total stored in _quantityTotal which you can then add to a footer or something else after the databinding has occurred like the OnDataBound event.
Yes, you will have to query the DB to get this value, or depending on what you are binding, loop through the collection you are binding and sum the values from the classes or DataSet/DataTable you are binding to it.
HTH.
I have a ListView control. I am displaying the data but once the user clicks the clear button
all the data that is shown in the ListView control should go off (empty). We should clear it contents and display a message no data to be displayed.
Even the paging (I am using DataPager control to achive paging) which was shown earlier when data was there should not be shown as we have cleared the data. My code looks like this:
protected void lvEmployee_DataBound(object sender, EventArgs e)
{
DropDownList ddl = DataPager1.Controls[1].FindControl("ddlPage") as DropDownList;
int PageCount = (DataPager1.TotalRowCount / DataPager1.PageSize);
if (PageCount*DataPager1.PageSize != DataPager1.TotalRowCount)
{
PageCount = PageCount + 1;
}
for (int i = 0; i < PageCount; i++)
{
ddl.Items.Add(new ListItem((i+1).ToString(),i.ToString()));
}
ddl.Items.FindByValue(CurrentPage.ToString()).Selected = true;
}
When I clear, all the data should go off and even the paging.
To clear all the values:
// in your .cs
lvEmployee.DataSource = null;
lvEmployee.DataBind();
To display a message when no data exists implement the EmptyDataTemplate:
// in your .aspx
<asp:ListView ID="lvEmployee" runat="server">
<EmptyDataTemplate>
No data available.
</EmptyDataTemplate>
</asp:ListView>