changing color of particular link button - asp.net

i am using a series of linkbuttons A-z which are dynamically created what i want on the click of each its text color change to something else to make it different from others what i am doing
protected void Page_Init(object sender, EventArgs e)
{
// Adding Dynamically linkbuttons for all alphabets(i.e. A-Z)
for (char asciiValue = 'A'; asciiValue <= 'Z'; asciiValue++)
{
LinkButton lbtnCharacter = new LinkButton();
lbtnCharacter.ID = "lbtnCharacter" + asciiValue;
divAlphabets.Controls.Add(lbtnCharacter);
lbtnCharacter.Text = Convert.ToString(asciiValue);
lbtnCharacter.CssClass = "firstCharacter";
lbtnCharacter.ToolTip = "Show users whose name starts with '" + Convert.ToString(asciiValue) + "'";
lbtnCharacter.CommandArgument = Convert.ToString(asciiValue);
lbtnCharacter.Command += new CommandEventHandler(lbtnCharacter_Command);
}
}
void lbtnCharacter_Command(object sender, CommandEventArgs e)
{
ViewState["Selected_Character"] = e.CommandArgument;
LinkButton lbtn = (LinkButton)divAlphabets.FindControl("lbtnCharacter" + e.CommandArgument);
lbtn.ForeColor = System.Drawing.Color.Orange;
txtNameFilter.Text = string.Empty;
BindUserList();
}
it is working fine but on clicking more then one buttons all the buttons which are clicked changes their color to orange but what i want is whichever button i click only that button color should change on click of next button previous button should go to default state is this approach right or tell me if it can be achieved by css

Your problem is that the ViewState of the linkbuttons is being saved just before the controls are rendered, including the updated styling. Then, on your postback, after Page_Init, the ViewState is re-applied to each control, with the orange styling. This overrides the setting that you add in Page_Init. So in Page_Load, you need to reset the styling on each of the controls.
Add another style to your stylesheet
.highlighted { color:orange; }
In lbtnCharacter_Command, replace
lbtn.ForeColor = System.Drawing.Color.Orange;
with
lbtn.CssClass = "firstCharacter highlighted ";
In Page_Load, add:
foreach (var ctrl in divAlphabets.Controls)
{
if (ctrl is LinkButton)
((LinkButton)ctrl).CssClass = "firstCharacter";
}
On each Page_Load, all of the linkbuttons css class will be reset to the default. This is after the ViewState has been applied to them (between PageInit and PageLoad). Then on the Command event, the clicked button will have the new style appended. The color setting in this style will override whatever color setting is in the firstCharacter style.
UPDATE
protected void Page_Init(object sender, EventArgs e) {
for (char asciiValue = 'A'; asciiValue <= 'Z'; asciiValue++) {
var lbtnCharacter = new LinkButton {
ID = "lbtnCharacter" + asciiValue,
Text = Convert.ToString(asciiValue),
ToolTip = "Show users whose name starts with '" + Convert.ToString(asciiValue) + "'",
CommandArgument = Convert.ToString(asciiValue)
};
lbtnCharacter.Command += lbtnCharacter_Command;
divAlphabets.Controls.Add(lbtnCharacter);
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (Session["CurrentLetter"] != null) {
foreach (var ctrl in divAlphabets.Controls) {
if (ctrl is LinkButton) {
if (((LinkButton) ctrl).Text == Session["CurrentLetter"].ToString()) {
((LinkButton) ctrl).CssClass = "firstCharacter highlighted";
}
}
}
}
}
void lbtnCharacter_Command(object sender, CommandEventArgs e) {
//Reset all of the other buttons only when clicking a new one
foreach (var ctrl in divAlphabets.Controls) {
if (ctrl is LinkButton) {
((LinkButton) ctrl).CssClass = "firstCharacter";
}
}
//Set the clicked button and save the Session state
var lbtn = (LinkButton)divAlphabets.FindControl("lbtnCharacter" + e.CommandArgument);
lbtn.CssClass = "firstCharacter highlighted";
Session["CurrentLetter"] = lbtn.Text;
}

Related

How can I delete a dynamical control from an UpdatePanel at the click of a button?

I have an ASP.NET UpdatePanel where I add other panels dynamically. Each of these smaller panels has their own "Delete" Button.
When I click on one of those "Delete" button, I want the corresponding panel to be deleted. Instead, what happens is: I press "Delete", nothing happens, then when I do another operation that causes a PostBack, the panel is deleted. (Too late)
I draw every dynamical control on PostBack and when I click the Delete button, its handler (which deletes the panel I want) only occurs after I draw every control, so I don't see any changes immediately.
Here's the code that is called on every postback:
private void drawForm()
{
if (Session["controls"] != null)
{
PlaceHolder1.Controls.Clear();
Ccontrols = (Dictionary<Label, Control>)Session["controls"];
int index = 1;
foreach (var entry in Ccontrols)
{
Panel cPanel = new Panel();
cPanel.CssClass = "controldiv";
cPanel.ID = "cpanel" + index;
Button closebtn = new Button();
closebtn.Text = "Delete";
closebtn.ID = "closebtn" + index++;
closebtn.Click += new EventHandler(closeControl);
cPanel.Controls.Add(entry.Key);
cPanel.Controls.Add(entry.Value);
cPanel.Controls.Add(closebtn);
cPanel.Controls.Add(new LiteralControl("<br />"));
cPanel.Controls.Add(new LiteralControl("<br />"));
closebtn.CssClass = "closebutton";
PlaceHolder1.Controls.Add(cPanel);
}
FormPanel.Update();
}
else
{
FormPanel.ContentTemplateContainer.Controls.Clear();
}
Here is the DeleteButton handler:
private void closeControl(object sender, EventArgs e)
{
String id = (sender as Button).ID;
PlaceHolder1.Controls.Remove(PlaceHolder1.FindControl("cpanel" + id));
foreach (Control c in (sender as Button).Parent.Controls)
{
if (c is Label)
{
Ccontrols.Remove((Label)c);
}
}
Session["controls"] = Ccontrols;
drawForm();
}
Thanks in advance
I think there is some problem with your triggers in UpdatePanel.
I would be able to help you better if you would post your html code where you have created your UpdatePanel.

ASP.NET dynamically added button click event doesnt work

In my webform app I have gridview with SQLDataSource. Now, I need to add button dynamically into one cell of each row (button must have value of cell) of this gridview. I added button for each cell, and also added click event for these buttons. But when I click these buttons click event doesn't work. Can everyone help?
protected void gvEmployee_RowDataBound(object sender, Obout.Grid.GridRowEventArgs e)
{
Button btn = new Button();
btn.Text = e.Row.Cells[8].Text;
if (e.Row.Cells[8].Text == "1")
{
btn.BackColor = Color.Red;
}
else
{
btn.BackColor = Color.Green;
}
e.Row.Cells[8].Text = "";
btn.Click += btn_Click;
e.Row.Cells[8].Controls.Add(btn);
}
protected void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
GridViewRow gvr = (GridViewRow)btn.NamingContainer;
}

Dynamically generating buttons in ASP.NET and passing values to Codebehind

I'm using a foreach loop to generate content how do I listen for a button click to call codebehind function. I can't set a value for a ASP button. How should I go about this ? When the user clicks on a button I want the ID for the user they clicked on to get passed to codebehind
You can pass the ID in the CommandArgument property of a button and you can assign the onclick event all inside the loop:
//for loop
//...
Button btn = new Button();
//etc
btn.CommandArgument = theID;
btn.Click += new EventHandler(btn_Click);
//...
//end for loop
protected void btn_Click(object sender, EventArgs e)
{
//Need to know which btn was clicked
Button btn = sender as Button;
if(btn == null)
{
//throw exception, etc
}
int id = Convert.ToInt32(btn.CommandArgument);
//etc
}
You can use Runtime generated Button Id to pass values to it.
//Counter for Dynamic Buttons.
int DynamicButtonCount = 1;
//This event generates Dynamic Buttons.
private void btnGenerate_Click(object sender, EventArgs e)
{
string name = "Dynamic Button_" + DynamicButtonCount;
Button btnDynamicButton = new Button();
btnDynamicButton.Name = name;
btnDynamicButton.Text = name;
btnDynamicButton.Id= DynamicButtonCount; //Use this id value
btnDynamicButton.Size = new System.Drawing.Size(200, 30);
btnDynamicButton.Location = new System.Drawing.Point(40, DynamicButtonCount * 40);
btnDynamicButton.Click += new EventHandler(this.btnDynamicButton_Click);
Controls.Add(btnDynamicButton);
DynamicButtonCount++;
}
//This event is triggered when a Dynamic Button is clicked.
protected void btnDynamicButton_Click(object sender, EventArgs e)
{
Button dynamicButton = (sender as Button);
MessageBox.Show("You clicked. " + dynamicButton.Name);
}

Gridview paging Show all Records

i have a gridview that has paging enabled. i also have a dropdown on the pager of the gridview where the user can select how many records per page they would like to retrieve. Once the dropdown is changed then an event is fired (shown below) to rerun the query with the updated results per page request. This works very well. I did however want to have a value "All" on the dropdown aswell and the method i used to impliment this is by disabling paging.
This all works brilliantly except for one issue. When the user selects "All" on the dropdown i would like to still show the pager once the gridview is updated. It doesnt show because i turned off paging but is there a way to show the pager again? See my code below for the event. (As you can see i renable the pager at the end but this has no effect)
thanks
damo
Code behind Event for Dropdown Change
void GridViewMainddl_SelectedIndexChanged(object sender, EventArgs e)
{
//changes page size
if ((((DropDownList)sender).SelectedValue).ToString() == "All")
{
GridViewMain.AllowPaging = false;
}
else
{
GridViewMain.PageSize = int.Parse(((DropDownList)sender).SelectedValue);
}
//binds data source
Result fAuditOverallStatusLatest = new Result(sConn);
GridViewMain.DataSource = Result.getAuditOverallStatusLatest();
GridViewMain.PageIndex = 0;
GridViewMain.DataBind();
GridViewMain.AllowPaging = true;
GridViewMain.BottomPagerRow.Visible = true;
GridViewMain.TopPagerRow.Visible = true;
}
DDL Code behind
protected void GridViewMain_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Pager)
{
DropDownList GridViewMainddl = new DropDownList();
//adds variants of pager size
GridViewMainddl.Items.Add("5");
GridViewMainddl.Items.Add("10");
GridViewMainddl.Items.Add("20");
GridViewMainddl.Items.Add("50");
GridViewMainddl.Items.Add("100");
GridViewMainddl.Items.Add("200");
GridViewMainddl.Items.Add("500");
GridViewMainddl.Items.Add("All");
GridViewMainddl.AutoPostBack = true;
//selects item due to the GridView current page size
ListItem li = GridViewMainddl.Items.FindByText(GridViewMain.PageSize.ToString());
if (li != null)
GridViewMainddl.SelectedIndex = GridViewMainddl.Items.IndexOf(li);
GridViewMainddl.SelectedIndexChanged += new EventHandler(GridViewMainddl_SelectedIndexChanged);
//adds dropdownlist in the additional cell to the pager table
Table pagerTable = e.Row.Cells[0].Controls[0] as Table;
TableCell cell = new TableCell();
cell.Style["padding-left"] = "15px";
cell.Controls.Add(new LiteralControl("Page Size:"));
cell.Controls.Add(GridViewMainddl);
pagerTable.Rows[0].Cells.Add(cell);
//add current Page of total page count
TableCell cellPageNumber = new TableCell();
cellPageNumber.Style["padding-left"] = "15px";
cellPageNumber.Controls.Add(new LiteralControl("Page " + (GridViewMain.PageIndex + 1) + " of " + GridViewMain.PageCount));
pagerTable.Rows[0].Cells.Add(cellPageNumber);
}
}
Put this in your Page_Init:
GridViewMain.PreRender += new EventHandler(GridViewMain_PreRender);
Then elsewhere in your Page class:
void GridViewMain_PreRender(object sender, EventArgs e)
{
var pagerRow = (sender as GridView).BottomPagerRow;
if (pagerRow != null)
{
pagerRow.Visible = true;
}
}
Then for your drop down event:
void GridViewMainddl_SelectedIndexChanged(object sender, EventArgs e)
{
MyServices fServices = new FAServices(sConn);
Result fAuditOverallStatusLatest = new Result(sConn);
var data = Result.getAuditOverallStatusLatest();
//changes page size
if ((((DropDownList)sender).SelectedValue).ToString() == "All")
{
GridViewMain.PageSize = data.Count();
}
else
{
GridViewMain.PageSize = int.Parse(((DropDownList)sender).SelectedValue);
}
//binds data source
GridViewMain.DataSource = data;
GridViewMain.PageIndex = 0;
GridViewMain.DataBind();
GridViewMain.AllowPaging = true;
}
In that PreRender event, you'll have to duplicate that code for the top pager.
Edit: To get All selected, make this change in GridViewMain_RowCreated:
if (li != null)
{
GridViewMainddl.SelectedIndex = GridViewMainddl.Items.IndexOf(li);
}
else
{
GridViewMainddl.SelectedIndex = GridViewMainddl.Items.Count - 1;
}

How to add an extra row (containing a Button and corresponding event handler) to the GridView

This must be something that a lot of people have done. Basically, it's a custom GridView (i.e. inherited control) with the ability to update all rows at once. I've tried putting the "update all" button in various places (footer, pager, outside the grid), but it looks neatest (to me) when the button is in an extra row as the last row of the GridView.
NB: The pager row is not a suitable place for this button because this custom control could be used in a situation where paging is false. Similarly, the normal footer may be required for some other purpose (e.g. totals).
Here's my code for putting the button in the correct place (with apologies for the terse variables etc.):
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
//Add an extra row to the table...
if (_updateAllEnabled)
{
GridViewRow r = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
Button btn = new Button();
TableCell c = new TableCell();
btn.ID = "UpdateAllButton"; // tried with and without this line
btn.Text = "Update All";
btn.Click += new EventHandler(UpdateAll);
r.Cells.Add(c);
c.Controls.Add(btn);
Table t = this.Controls[0] as Table;
c.ColumnSpan = this.Columns.Count;
t.Rows.Add(r);
}
}
This gives the appearance that I want, but the click event (UpdateAll) does not fire.
I assume that the stuff is being added too late in the life cycle (PreRender), but where else can I do this to ensure that the row is at the end of the GridView? I also thought that there might be trouble identifying the button, so I tried setting the ID. In any case, the ID in the generated HTML looks OK (consistent with "working" buttons in the pager row.
Is there a way for me to achieve this or am I attempting the impossible?
The best place to create your footer-controls is RowCreated since that's early enough in the lifecycle and also ensures that their recreated on every postback:
Footer approach:
protected void Grid_RowCreated(Object sender, GridViewRowEventArgs e) {
if(e.Row.RowType == DataControlRowType.Footer) {
Button btn = new Button();
TableCell c = new TableCell();
btn.ID = "UpdateAllButton";
btn.Text = "Update All";
btn.Click += new EventHandler(UpdateAll);
var firstCell=e.Row.Cells[0];
firstCell.ColumnSpan =e.Row.Cells.Count;
firstCell.Controls.Add(btn);
while(e.Row.Cells.Count > 1)e.Row.Cells.RemoveAt(e.Row.Cells.Count-1);
}
}
Of course you have to set ShowFooter to true:
<asp:GridView ID="GridView1"
ShowFooter="true"
OnRowCreated="Grid_RowCreated"
runat="server"
</asp:GridView>
Pager approach:
In my opinion this is the purpose of the FooterRow. But if you really want to ensure that your Button is in the very last row of a GridView(even below Pager as commented), i would try my next approach.
Here I'm using the pager for your costom control(s) by adding another TableRow to the PagerTable which inherits from Table.
protected void Grid_RowCreated(Object sender, GridViewRowEventArgs e) {
switch(e.Row.RowType){
case DataControlRowType.Pager:
Button btnUpdate = new Button();
btnUpdate.ID = "UpdateButton";
btnUpdate.Text = "Update";
btnUpdate.Click += new EventHandler(UpdateAll);
var tblPager = (Table)e.Row.Cells[ 0 ].Controls[ 0 ];
var row = new TableRow();
var cell = new TableCell();
cell.ColumnSpan = tblPager.Rows[ 0 ].Cells.Count;
cell.Controls.Add(btnUpdate);
row.Cells.Add(cell);
tblPager.Rows.Add(row);
break;
}
}
To ensure that the pager is visible even if only one page is shown(note that the real pager is invisible if PageSize==1):
protected void Grid_PreRender(object sender, EventArgs e){
GridView gv = (GridView)sender;
GridViewRow gvr = (GridViewRow)gv.BottomPagerRow;
if(gvr != null) {
gvr.Visible = true;
var tblPager = (Table)gvr.Cells[ 0 ].Controls[ 0 ];
//hide real pager if unnecessary
tblPager.Rows[ 0 ].Visible = GridView1.PageCount > 1;
}
}
Of course now you have to set AllowPaging=true:
<asp:GridView ID="GridView1"
AllowPaging="true"
PagerSettings-Mode="NumericFirstLast"
OnRowCreated="Grid_RowCreated"
OnPreRender="Grid_PreRender"
OnPageIndexChanging="Grid_PageChanging"
runat="server">
</asp:GridView>
Final approach(working for a custom GridView and all PagerPositions):
public PagerPosition OriginalPagerPosition{
get { return (PagerPosition)ViewState[ "OriginalPagerPosition" ]; }
set { ViewState[ "OriginalPagerPosition" ] = value; }
}
protected void Page_Load(object sender, EventArgs e){
if(!IsPostBack) OriginalPagerPosition = GridView1.PagerSettings.Position;
GridView1.PagerSettings.Position = PagerPosition.TopAndBottom;
GridView1.AllowPaging = true;
// databinding stuff ...
}
Keep the RowCreated the same as above in Pager approach.
Visibility of top/bottom pagers will be controlled in PreRender according to the OriginalPagerPosition property. Both pagers are created even with PagerPosition=TOP, the bottom pager is required for your additional control(s):
protected void Grid_PreRender(object sender, EventArgs e)
{
GridView gv = (GridView)sender;
GridViewRow tpr = (GridViewRow)gv.TopPagerRow;
GridViewRow bpr = (GridViewRow)gv.BottomPagerRow;
tpr.Visible = gv.PageCount > 1 && (OriginalPagerPosition == PagerPosition.Top || OriginalPagerPosition == PagerPosition.TopAndBottom);
bpr.Visible = true;
var tblBottomPager = (Table)bpr.Cells[ 0 ].Controls[ 0 ];
tblBottomPager.Rows[ 0 ].Visible = gv.PageCount > 1 && (OriginalPagerPosition == PagerPosition.Bottom || OriginalPagerPosition == PagerPosition.TopAndBottom);
var tblTopPager = (Table)tpr.Cells[ 0 ].Controls[ 0 ];
tblTopPager.Rows[1].Visible = false;
}
Note: if you are extending the GridView control, you have to replace all occurences of GridView1(my test-grid) with this.
It would be easy to add an extra row into the grid. But the difficulty in your requirement is that the GridView's RowCollection should not contain this row since that would be error-prone. It should also be the very last row even if paging is enabled. This is (afaik) not possible.
Hence i've chosen to extend the pager with this functionality.
I'll add this as separate answer since my other is already too detailed and describes two different ways(footer,pager) to add controls to a GridView without extending it.
This approach extends a GridView as in your own requirement and is similar to my other pager-approach. But it's cleaner and only adds the additional row to the BottomPager. It woks also for every setting(AllowPaging=false,Pager-Position: Top,Bottom,BottomTop):
[DefaultProperty("EnableUpdateAll")]
[ToolboxData("<{0}:UpdateGridView runat=server></{0}:UpdateGridView>")]
public class UpdateGridView : GridView
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("true")]
[Localizable(true)]
public bool EnableUpdateAll
{
get
{
Object val = ViewState["EnableUpdateAll"];
return ((val == null) ? true : (bool)val);
}
set
{
ViewState["EnableUpdateAll"] = value;
}
}
private bool OriginalAllowPaging
{
get
{
Object val = ViewState["OriginalAllowPaging"];
return (bool)val;
}
set
{
ViewState["OriginalAllowPaging"] = value;
}
}
private PagerPosition OriginalPagerPosition
{
get
{
Object val = ViewState["OriginalPagerPosition"];
return (PagerPosition)val;
}
set
{
ViewState["OriginalPagerPosition"] = value;
}
}
protected override void OnInit(System.EventArgs e)
{
if (ViewState["OriginalPagerPosition"] == null)
OriginalPagerPosition = base.PagerSettings.Position;
if(OriginalPagerPosition != PagerPosition.Bottom)
PagerSettings.Position=PagerPosition.TopAndBottom;
if (ViewState["OriginalAllowPaging"] == null)
OriginalAllowPaging = base.AllowPaging;
base.AllowPaging = true;
}
protected override void OnRowCreated(GridViewRowEventArgs e)
{
switch (e.Row.RowType)
{
case DataControlRowType.Pager:
//check if we are in BottomPager
if (this.Rows.Count != 0 && this.EnableUpdateAll)
{
Button btnUpdate = new Button();
btnUpdate.ID = "BtnUpdate";
btnUpdate.Text = "Update";
btnUpdate.Click += new EventHandler(UpdateAll);
var tblPager = (Table)e.Row.Cells[0].Controls[0];
var row = new TableRow();
var cell = new TableCell();
cell.ColumnSpan = tblPager.Rows[0].Cells.Count;
cell.Controls.Add(btnUpdate);
row.Cells.Add(cell);
tblPager.Rows.Add(row);
}
break;
}
}
protected override void OnPreRender(EventArgs e)
{
bool bottomPagerVisible =
OriginalAllowPaging &&
PageCount > 1 &&
(OriginalPagerPosition == PagerPosition.Bottom || OriginalPagerPosition == PagerPosition.TopAndBottom);
BottomPagerRow.Visible = bottomPagerVisible || EnableUpdateAll;
var tblBottomPager = (Table)BottomPagerRow.Cells[0].Controls[0];
tblBottomPager.Rows[0].Visible = bottomPagerVisible;
}
private void UpdateAll(Object sender, EventArgs e)
{
// do something...
}
}

Resources