How to scroll to selected row in GridView - c#

I have a GridView with PageSize = 20 (20 rows) but it can show only 10 rows without a vertical scrollbar appearing.
My problem is that when a postback occurs, it jumps to top row of the grid even though I selected a different row. I would like to scroll to the selected row. How can I do this?

Add MaintainScrollPositionOnPostback in your page directive.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" MaintainScrollPositionOnPostback ="true"%>
Another way, use a scrollTop method of the DIV that wraps your GridView:
private void ScrollGrid()
{
int intScrollTo = this.gridView.SelectedIndex * (int)this.gridView.RowStyle.Height.Value;
string strScript = string.Empty;
strScript += "var gridView = document.getElementById('" + this.gridView.ClientID + "');\n";
strScript += "if (gridView != null && gridView.parentElement != null && gridView.parentElement.parentElement != null)\n";
strScript += " gridView.parentElement.parentElement.scrollTop = " + intScrollTo + ";\n";
ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "ScrollGrid", strScript, true);
}
EDIT:
This won't work for several reasons:
1) if the gridView is inside a NamingContainer control, like a Panel, because the Id on the client side won't be the ClientId. You need to use the UniqueId of teh control instead.
2) you can't trust the row height to calculate the scroll position. If the text in any column wraps to more than one line, or any row contains something higher than the style, the size of the row will be different
3) different browsers can have different behaviors. You're better of using jQuery scrollTop() and scroll() functions. To use them, you must use scrollTop on client side and set the value of a HiddenControl that can be read on server side to reset the position. You can't get the height of the rows in the browser until they are rendered on client side.

This code in the RowDataBound event handler for the gridview worked for me:
protected void dgv_usersRowDatabound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowIndex == intEditIndex)
{
DropDownList drpCategory = e.Row.FindControl("drpCategory") as DropDownList;
drpCategory.Focus();
}
}
The Gridview contains a dropdownlist in each row as an EditItemTemplate.

This worked for me, and required no ASP.NET AJAX, UpdatePanel or cookie, and a lot less JavaScript than other solutions I've seen.
<input type="hidden" runat="server" id="hdnScroll" value="0" />
<div style="height:600px; overflow-x:hidden; overflow-y:scroll">
<asp:GridView runat="server" ID="myGridView" OnRowDataBound="myGridView_RowDataBound" OnSelectedIndexChanged="myGridView_SelectedIndexChanged">
...
</asp:GridView>
</div>
Then
protected void myGridView_SelectedIndexChanged(object sender, EventArgs e) {
//if(gr != null) gr.SelectedRow.Cells[0].Focus(); // Only works on an editable cell
hdnScroll.Value = (myGridView.SelectedIndex * (int)myGridView.RowStyle.Height.Value).ToString();
}
Finally back in the .aspx, to run upon postback
<script type="text/javascript">
$(function() {
document.getElementById('<%=myGridView.ClientID%>').scrollTop = $('#hdnScroll').val();
});

Related

div from gridview - onclick width changing

can somebody tell me following code in asp.net c# codebehind.
If i click and select any row in gridview ---> change CSS-DIV width, which runat server.
And where do i have to paste it? i tryed few things, but it doesnt matter where i code it, the width changes on page_load instead of "on gridview click"
Generally i need it for that scheme http://ipic.su/img/img7/fs/ChangeWidth.1412455799.jpg
Thanks for any advises!
Try this:
if (!Page.IsPostBack)
{
dvtimeSheet.Visible = false;
//hide your details view
}
Add On OnSelectedIndexChanging Event to GridView
OnSelectedIndexChanging="gvTimeSheet_OnSelectedIndexChanged"
and Use In Code Behind
protected void gvTimeSheet_OnSelectedIndexChanged(Object sender, EventArgs e)
{
gvTimeSheet.Visible = false;
dvtimeSheet.Visible = true;
dvtimeSheet.Style.Add("left", "120px");
dvtimeSheet.Style.Add("height", "260px");
dvtimeSheet.Style.Add("width", "120px");
dvtimeSheet.Style.Add("position", "absolute");
//same you can do with your div(making true/false or adding style)
}
Note: Use Update Panels with EnableEventValidation="false" in Page Directives
and Use Firebug for mozilla to adding style and alignments
EDIT:

ASP.NET checkbox values only available after second postback

I have a problem with the availability of the values of checkboxes and dropdownlists in my webforms page. I think that there is something obvious that I can't see. There is probably a mistake in my idea so I won't post the whole code for now.
What I want to do:
On my page there is a survey (textboxes, checkboxes and dropdowns) and a scroll fixed panel (it stays at the same position in the browser window when scrolling). Depending on the selections made the fixed panel should show information. This information should update everytime a checkbox is un/checked or a dropdown is selected.
What I have done:
The survey is created programmatically on first page_load and added to a panel (=Panel1). There are two languages so I create the every item of the survey twice and store its panel in the browser session (don't know if thats the right way to achieve this but it seems to work). That means I get the whole English survey from "langPanels["EN"].
Default.aspx.cs:
protected void Page_Load(object sender, EventArgs e) {
if (IsPostBack) {
langPanels = (Dictionary<String,Panel>) HttpContext.Current.Session["panels"];
Panel1.Controls.Clear();
Panel1.Controls.Add(langPanels[SelectLanguage.SelectedValue]);
updateQuestions(); //Survey is evaluated and information is stored in weigthDictionary and blockedResults
ranking.Text = PrintKeysAndValues(weigthDictionary, blockedResults);
}
else {
createLanguageSelectionList(); //Here the dropdown for the different languages is created
createLanguagePanels(); //Here all language surveys are created and stored to the current session
}
}
Default.aspx:
<%# Page Title="Welcome" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="class._Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="BodyContent" runat="server">
<asp:DropDownList ID="SelectLanguage" runat="server" AutoPostBack="true" OnSelectedIndexChanged="SelectLanguage_Change"/><br />
<asp:Panel ID="Panel1" runat="server"/>
</asp:Content>
[EDIT1:]
Creating of the checkboxes (this.panel is afterwards added to langPanels. Method is called whithin createLanguagePanels):
[/EDIT]
private void asp_createCheckboxQuestion(String question, String questionID, String[] checkboxes, String[] answerIDs) {
Label questionLabel = new Label();
questionLabel.Text = question;
this.panel.Controls.Add(questionLabel);
this.panel.Controls.Add(new LiteralControl("<br />"));
CheckBoxList checkBoxList = new CheckBoxList();
checkBoxList.ID = questionID;
checkBoxList.AutoPostBack = true;
checkBoxList.CellPadding = 5;
checkBoxList.CellSpacing = 5;
checkBoxList.RepeatColumns = 1;
checkBoxList.RepeatDirection = RepeatDirection.Vertical;
checkBoxList.RepeatLayout = RepeatLayout.Table;
checkBoxList.TextAlign = TextAlign.Right;
checkBoxList.EnableViewState = true;
for (int i = 0; i < checkboxes.Length; i++) {
ListItem item = new ListItem();
item.Text = checkboxes[i];
item.Value = answerIDs[i];
checkBoxList.Items.Add(item);
}
this.panel.Controls.Add(checkBoxList);
this.panel.Controls.Add(new LiteralControl("<br />"));
}
Everything works fine except that the information in the fixed panel only is available after I clicked a second checkbox. For example there are 3 checkboxes. The first is clicked and nothing happens in the fixed panel. The second one is clicked and the panel shows information for the first checkbox. The third one is clicked and the panel shows information for first and second checkbox. [EDIT2:] Although their checked states persists through the autoPostBack.[/EDIT]
Ok I found my mistake:
The problem was that I chose the detour through the browser session. That way the values of the survey were only known after a second postback. I solved it by creating the survey everytime a postback is executed:
if (IsPostBack) {
Panel p = createLanguagePanels();
Panel1.Controls.Clear();
Panel1.Controls.Add(p);
}
else {
createLanguageSelectionList();
Panel p = createLanguagePanels();
Panel1.Controls.Clear();
Panel1.Controls.Add(p);
}
I don't know why the selected values are still be selected after postback (they are newly created each time!?), but they do. I know this is an awful solution so if there are better ways of doing this I will appreciate knowing about them!

List of Hyperlinks, buttons, whatever that open to new browser window

I have a need to create a small window inside of a ASP.NET Web Page(aspx) which displays a list of usernames, when you click the username, I need a new broswer window (not tab) to open up to a specific size. I can handle opening the new browser window assuming whatever control I use gets me into a code behind function where I can call....
string url = "http://www.dotnetcurry.com";
ScriptManager.RegisterStartupScript(this, this.GetType(), "OpenWin", "<script>openNewWin ('" + url + "')</script>", false);
Here's the markup that's in the page for the link.
<script language="javascript" type="text/javascript">
function openNewWin(url) {
var x = window.open(url, 'mynewwin', 'width=600,height=600,toolbar=1');
x.focus();
}
</script>
1.) What controls should I be using for this problem, what does the structure look like after I get the respective usernames back from the database?
Here's the closest I've come...This code uses an ASP.NET Bulleted List which I'm trying to bind to a list of HTML links which I would like to instead not POINT anywhere, but get me to the codebehind. Instead this Code actually renders on the page as the HTML (it isn't parsed into hyperlinks..)
protected void Page_Load(object sender, EventArgs e)
{
UsersBulletedList.DataSource = theContext.GetOnlineFavorites(4);
UsersBulletedList.DataBind();
}
public IQueryable<String> GetOnlineFavorites(int theUserID)
{
List<String> theUserList = new List<String>();
IQueryable<Favorite> theListOfFavorites= this.ObjectContext.Favorites.Where(f => f.SiteUserID == theUserID);
foreach (Favorite theFavorite in theListOfFavorites)
{
string theUserName = this.ObjectContext.SiteUsers.Where(su => su.SiteUserID == theFavorite.FriendID && su.LoggedIn == true).FirstOrDefault().UserName;
yourOnlineFavorites.Add("<a href='RealTimeConversation.aspx?UserName=" + theUserName + "'>" + theUserName + "</a>");
//this needs to help me get into a codebehind method instead of linking to another page.
}
return yourOnlineFavorites.AsQueryable();
}
I would create a Repeater on your page and bind your results from the GetOnlineFavorites method. Inside the Repeater, place a LinkButton with a ItemCommand event that adds your script to the page.
Markup:
<asp:Repeater ID="repeater" runat="server" OnItemCommand="repeater_ItemCommand">
<ItemTemplate>
<asp:LinkButton runat="server" ID="linkButton"
Text='<%# Eval("PropertyFromBindingCollection") %>'
CommandName="OpenWindow"
CommandArgument='<%# Eval("AnotherProperty") %>' />
</ItemTemplate>
</asp:Repeater>
In here, the Text property of the LinkButton and the CommandArgument of the Repeater would be set to some properties from your collection.
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
repeater.DataSource = theContext.GetOnlineFavorites(4);
repeater.DataBind();
}
}
protected void repeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
if(e.CommandName == "OpenWindow")
{
string arg = e.CommandArgument; // this could be the url, or a userID to get favorites, or...?
//Your open window script
}
}
Now, when the user clicks one of the LinkButtons, it will fire the ItemCommand event for the Repeater, check the CommandName (set on the LinkButton), and then get the CommandArgument set on the LinkButton. If you set the CommandArgument as a URL, you can use that in your OpenWin script, otherwise use whatever data you set as the argument to get the URL you want to open.

Add CSS Class through a Repeater

I have a repeater which dynamically generate tab links using Sitecore (sc:Link) like this:
<asp:Repeater ID="rptTab" runat="server" OnItemDataBound="rptTab_ItemBound">
<ItemTemplate>
<li id= "liTabTest" runat = "server" class="tab-label">
<asp:HyperLink onclick = "javascript: TabClick(this)" runat="server" id="aLink">
<sc:Link ID="hlTabLink" Field="scTabLink" runat="server" ></sc:Link>
</asp:HyperLink>
</li>
</ItemTemplate>
</asp:Repeater>
I manipulate the CSS via JS:
var loadURL;
$(document).ready(function () {
init();
});
function init() {
$("ul#Tab-labels li:first").addClass("TabbedPanelsTabSelected");
};
function TabClick(obj) {
$("ul#Tab-labels li").removeClass("TabbedPanelsTabSelected");
$(obj).addClass("TabbedPanelsTabSelected");
};
Unfortunately, this is not working because each tab is a separate .ASPX page, so the page is getting rendered again and that is why Init() in JS is getting called and CSS is getting executed to the first item everytime.
This is my code behind:
protected void rptTab_ItemBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Item i = e.Item.DataItem as Item;
Link hlTabLink = e.Item.FindControl("hlTabLink") as Link;
hlTabLink.DataSource = i.Paths.FullPath;
hlTabLink.Field = "Title";
HyperLink aLink = e.Item.FindControl("aLink") as HyperLink;
aLink.NavigateUrl = Sitecore.Links.LinkManager.GetItemUrl(i);
}
}
I tried adding CSS through code-behind but it didnt work because I cannot get the index of the tab (which tab is getting selected). Any solution will be appreciated! Thanks!
Don't run javascript for a task that is better (and easier) accomplished in code-behind. Just set the active class for the repeater item where Sitecore.Context.Item matches the name of the tab. Pseudo code inside ItemDataBound:
if(i == Sitecore.Context.Item)
{
HtmlGenericControl li = e.Item.FindControl("liTabTest");
li.Attributes.Add("class","TabPanelTabbedSelected");
}
Not sure if HtmlGenericControl is correct here, or if it has a CssClass property, but I hope you get the idea. If there is no direct representation for li on the server side, you can also bind a string literal or use a Literal control.
The answer to my question is: The repeater is like an array. So I can get the 1st and Last element of a repeater like this:
string currClass = hc.Attributes["class"].ToString();
string count = e.Item.Controls.Count.ToString();
if (e.Item.ItemIndex == 0)
{
currClass += " TabbedPanelsTabSelected";
}
else if (e.Item.ItemIndex.ToString() == count)
{
currClass += " last";
}
In this way I can add a css to my first element and the last element through Repeater.

Mutually exclusive selection of Radiobutton in gridView.ASP.NET C#

<asp:TemplateField HeaderText="Select One">
<ItemTemplate>
<asp:RadioButton ID="RadioButton1" runat="server" />
</ItemTemplate>
</asp:TemplateField>
aspx.cs
protected void Button1_Click(object sender, EventArgs e)
{
foreach (GridViewRow di in GridView1.Rows)
{
RadioButton rad = (RadioButton)di.FindControl("RadioButton1");
if (rad.Checked&&rad!=null)
{
s = di.Cells[1].Text;
}
}
Response.Redirect("applicants.aspx?form=" +s);
}
I'm selecting the rows that are selected with this but I have a problem here I want user to be able to select only one radiobutton but its allowing all the radiobuttons to be selected at once.Can you help me in removing this problem please.
please.
Maybe I'm too late here on the party but this will do the trick,
check out here......
This might be useful for someone watching this answer in the future.
In the ASP page you need to set the GroupName property to be the same for all the radio buttons, e.g.:
<asp:RadioButton ID="RadioButton1" runat="server" GroupName="RadioGroup" />
well for that you can use follwing code
first of all you should define the groupName.The follwing code will work
<asp:RadioButton ID="RadioButton1" OnCheckedChanged="rbSelector_CheckedChanged" AutoPostBack="true" GroupName="Apply" runat="server"></asp:RadioButton>
C#
protected void rbSelector_CheckedChanged(object sender, System.EventArgs e)
{
foreach (GridViewRow oldrow in GridView2.Rows)
{
((RadioButton)oldrow.FindControl("RadioButton1")).Checked = false;
}
//Set the new selected row
RadioButton rb = (RadioButton)sender;
GridViewRow row = (GridViewRow)rb.NamingContainer;
((RadioButton)row.FindControl("RadioButton1")).Checked = true;
}
You can try this link to select single radiobutton in grid : http://www.c-sharpcorner.com/uploadfile/krishnasarala/select-single-radio-button-in-gridview-in-Asp-Net/
Using the GroupName property by itself won't work, each radio button will still get a unique name attribute since they're in different rows of the grid.
One option is to emit the radio button markup manually using a Literal control (example). This will make it easy to group the radio buttons on the client-side, but requires a bit more work to determine which button was selected on postback.
When I needed this behavior, I found it easier to keep the radio buttons as server-side controls, and just enforce the button group w/ jQuery. Put your RadioButton in a TemplateField as you've shown, then add this code to uncheck all the other buttons when one is checked:
$(document).ready(function () {
// could also pass in a unique ID selector
createManualRadioButtonGroupForGridView(".myGridViewClass");
});
function createManualRadioButtonGroupForGridView(gridViewSelector) {
$(gridViewSelector + " input[type=radio]").change(function () {
var checkedRadioButton = this;
$(gridViewSelector + " input[type=radio]").each(function (e) {
if (this !== checkedRadioButton) {
$(this).prop("checked", false);
}
});
});
}

Categories