I have a gridview. The gridview has a textbox multiline that keeps an text. After that I have a column with imagebutton named approved, and one named not approved. I want to force the user before click approved or not approved to read the text inside the multiline box. How can I achieve this programmatically? I know I should create a Rowdatabound Event, but what I should do with the code? I am using c# ASP.NET web application.
I know you can track the scroll bar of the browser using javascript but I've personally never come across similar functionality for a text box. I would suggest trying a slightly different approach, why don't you add an extra column to you grid view which has a check box control for - I've read and accepted the agreement. And the Approve button will only be enabledd when the checkbox is checked, here's an example:
ASPX:
<div>
<asp:ScriptManager ID="sm" runat="server" />
<asp:UpdatePanel ID="updatePanel" runat="server">
<ContentTemplate>
<asp:GridView ID="grid" runat="server" AutoGenerateColumns="false" OnRowDataBound="grid_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox TextMode="MultiLine" runat="server" ID="txtAgreement" Text='<%# Eval("Agreement") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
I have read and accepted the agreement
<asp:CheckBox ID="chkAgreement" AutoPostBack="true" runat="server" OnCheckedChanged="CheckedChanged" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnAccept" runat="server" Text="Accept" OnClick="Accept" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
Code behind:
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var items = new List<License> { new License { Agreement = "Agreement 1" }, new License { Agreement = "Agreement 2" } };
grid.DataSource = items;
grid.DataBind();
}
}
protected void Accept(object sender, EventArgs e)
{
}
protected void grid_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
(e.Row.FindControl("btnAccept") as Button).Enabled = false;
}
protected void CheckedChanged(object sender, EventArgs e)
{
var chkAgreement = sender as CheckBox;
Button btnAccept = null;
if (chkAgreement != null)
{
var row = chkAgreement.Parent.Parent as GridViewRow;
btnAccept = row.FindControl("btnAccept") as Button;
if (btnAccept != null)
if (chkAgreement.Checked)
btnAccept.Enabled = true;
else
btnAccept.Enabled = false;
}
}
}
public class License
{
public string Agreement { get; set; }
}
Related
Error on RowUpdating >> GridView 'GView' fired the RowUpdating event, which was not handled.
I put the RowEditing and I can enter to update the data, but when I put public void GView_UpdateItem(int id) {} it returns the error saying GridView 'GView' triggered the RowUpdating event, which was not handled.
<asp:GridView runat="server" ID="GView" CellPadding="4" ForeColor="#333333" GridLines="None" OnRowEditing="GView_RowEditing" UpdateMethod="GView_UpdateItem">
<AlternatingRowStyle BackColor="White"></AlternatingRowStyle>
<Columns>
<asp:CommandField ShowEditButton="True"></asp:CommandField>
<asp:CommandField ShowDeleteButton="True"></asp:CommandField>
</Columns>
C# CODE
protected void Page_Load(object sender, EventArgs e)
{
}
public static List<Contato> contatos = new List<Contato>();
public void btnCad(object sender, EventArgs e)
{
Contato contato = new Contato();
contato.Id = contatos.Count;
contato.Nome = this.txtNome.Text;
contato.Idade = this.txtIdade.Text;
contato.Telefone = this.txtTelefone.Text;
contato.Genero = this.txtGenero.Text;
contato.DataCadastro = this.txtDataCad.Text;
contatos.Add(contato);
GView.DataSource = contatos;
GView.DataBind();
}
public void GView_UpdateItem(int id)
{
VoxTraining.Models.Contato item = contatos.Find(cont => cont.Id == id);
if (item == null)
{
ModelState.AddModelError("", String.Format("O item com id {0} não foi encontrado", id));
return;
}
TryUpdateModel(item);
if (ModelState.IsValid)
{
}
}
protected void GView_RowEditing(object sender, GridViewEditEventArgs e)
{
return ;
}
Ok, a few things.
Yes, we can do this without a database. We have have to persist our "list of names".
Dump the delete and edit buttons for the GV - they not worth the trouble - they don't help you.
So, we have the edit area, and the grid.
So, we have this markup:
<div id="myedit" runat="server" style="width:30%;padding:35px;display:none">
<div cssclass="form-group">
<label for="exampleInputEmail1">Nome</label>
<asp:TextBox CssClass="form-control" runat="server" ID="txtNome"></asp:TextBox>
</div>
<div cssclass="form-group">
<label for="exampleInputPassword1">Idade</label>
<asp:TextBox CssClass="form-control" runat="server" ID="txtIdade"></asp:TextBox>
</div>
<div cssclass="form-group">
<label for="exampleInputPassword1">Telefone</label>
<asp:TextBox CssClass="form-control" runat="server" ID="txtTelefone"></asp:TextBox>
</div>
<asp:Label runat="server" AssociatedControlID="txtGenero" ><b>Genero</b></asp:Label><br />
<asp:DropDownList CssClass="form-group" checked="" ID="txtGenero" runat="server" OnSelectedIndexChanged="btnCad">
<asp:ListItem Text="Masculino" />
<asp:ListItem Text="Feminino" />
</asp:DropDownList>
<div cssclass="form-group">
<label for="exampleInputPassword1">Data de Cadastro</label>
<asp:TextBox CssClass="form-control" runat="server" TextMode="Date" ID="txtDataCad"></asp:TextBox>
</div>
<br />
<asp:Button runat="server" ID="IDbtnCad" CssClass="btn" Text="Save" OnClick="btnCad" />
<asp:Button runat="server" ID="btnCancel" CssClass="btn" Text="Cancel" OnClick="btnCancel_Click"
style="margin-left:20px" />
<asp:Button runat="server" ID="btnDelete" CssClass="btn" Text="Delete" OnClick="btnCancel_Click"
style="margin-left:30px" />
</div>
<div id="MyGrid" runat="server">
<asp:Button ID="cmdNew" runat="server" Text="+Add new" CssClass="btn" OnClick="cmdNew_Click"/>
<asp:GridView runat="server" ID="GView" CellPadding="4" ForeColor="#333333" cssclass="table" Width="40%"
ShowHeaderWhenEmpty="true" >
<Columns>
<asp:TemplateField HeaderText="Edit" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdEdit" runat="server" Text="Edit" CssClass="btn" OnClick="cmdEdit_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White"></HeaderStyle>
</asp:GridView>
</div>
And code to load is this:
List<Contato> MyNames = new List<Contato>();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["MyNames"] = MyNames;
GView.DataSource = MyNames;
GView.DataBind();
}
else
MyNames = ViewState["MyNames"] as List<Contato>;
}
Note how we save the list of names.
So, we now have this:
so, add new button is thus this:
protected void cmdNew_Click(object sender, EventArgs e)
{
// add new
Contato OneName = new Contato();
MyNames.Add(OneName);
MyEdit(MyNames.Count - 1);
}
And my edit is this:
void MyEdit(int RowIndex)
{
Contato OneName = MyNames[RowIndex];
txtNome.Text = OneName.Nome;
txtIdade.Text = OneName.Idade;
txtTelefone.Text = OneName.Telefone;
txtGenero.Text = OneName.Genero;
txtDataCad.Text = OneName.DataCadastro;
ViewState["RowIndex"] = RowIndex;
// show editor, hide grid
myedit.Style.Add("Display", "nomral");
MyGrid.Style.Add("display", "none");
}
so, we hit add, and we now have this:
We hit save button, this code
protected void btnCad(object sender, EventArgs e)
{
int RowIndex = (int)ViewState["RowIndex"];
Contato OneName = MyNames[RowIndex];
OneName.Nome = this.txtNome.Text;
OneName.Idade = this.txtIdade.Text;
OneName.Telefone = this.txtTelefone.Text;
OneName.Genero = this.txtGenero.Text;
OneName.DataCadastro = txtDataCad.Text;
ViewState["MyNames"] = MyNames;
myedit.Style.Add("Display", "none");
MyGrid.Style.Add("display", "normal");
GView.DataSource = MyNames;
GView.DataBind();
}
And we now have this:
We can use add again, and now this:
the edit row button - plane jane asp.net button click.
Code is this:
protected void cmdEdit_Click(object sender, EventArgs e)
{
Button btnEdit = sender as Button;
GridViewRow gRow = btnEdit.NamingContainer as GridViewRow;
MyEdit(gRow.RowIndex);
}
So, hitting edit button, goes back to the editor.
Say like this:
Cancel button - does nothing (no save, return to grid).
Say this:
protected void btnCancel_Click(object sender, EventArgs e)
{
myedit.Style.Add("Display", "none");
MyGrid.Style.Add("display", "normal");
}
And the delete button - that would just remove the current row index item from the list.
eg:
protected void cmdDel_Click(object sender, EventArgs e)
{
myedit.Style.Add("Display", "none");
MyGrid.Style.Add("display", "normal");
int RowIndex = (int)ViewState["RowIndex"];
MyNames.RemoveAt(RowIndex);
GView.DataSource = MyNames;
GView.DataBind();
}
Here I have kept two button(btnhide and btnunhide) and a label inside the repeater and I have made button btnunhide invisible initially. Now what I want is that as I press button btnhide then btnunhide which is invisible intially should be visible.
Solution Will Be great help.
Html used
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="Repeater1_ItemCommand" >
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:Button ID="btn" CommandName="h" runat="server" Text="Hide" />
<asp:Button ID="btnhide" Visible="false" runat="server" Text="Unhide" />
</ItemTemplate>
</asp:Repeater>
Code behind
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "h")
{
}
}
You can achieve this by just a single button by changing the Text to hide/unhide and do the functionality as required by just checking the Text property of the button.
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "h")
{
Button btn = (Button)(e.CommandSource);
if(btn.Text == "hide")
{
btn.Text = "unhide";
//Do additional work here, when unhiding.
}
else
{
btn.Text = "hide";
//Do additional work here, when hiding.
}
}
}
I Hope, this helps. Thanks
Is there some way to pass the unique client id to codebehind? I have a imagebutton in a gridview and I wish to do something like this:
<asp:ImageButton ID="imbView" runat="server" ToolTip="View details" ImageUrl="~/css/images/View.png" CommandName="wView" CommandArgument='#<%=imbView.ClientID%>' />
On debugging though I see that my CommandArgument is #<%=imbView.ClientID%>..
To specify: I want to pass something that uniquely identifies generated elements (and I thought that the ClientID would be a good way to identify it).
Huh ?
Assuming you have
<asp:ImageButton ID="imbView" runat="server" ToolTip="View details" ImageUrl="~/css/images/View.png" CommandName="wView" OnCommand="aaa" />
then -
protected void aaa(object sender, CommandEventArgs e)
{
var a= (sender as Control).ClientID;
}
Here is how you retrieve CommandArgument inside RowCommand event.
You can also use e.CommandSource as ImageButton inside RowCommand event.
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False"
OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Detail">
<ItemTemplate>
<asp:ImageButton ID="imbView" runat="server"
ToolTip="View details" ImageUrl="~/css/images/View.png"
CommandName="wView"
CommandArgument='<%# Eval("Id") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Name" DataField="Name">
</asp:BoundField>
</Columns>
</asp:GridView>
Code Behind
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridView1.DataSource = new List<Item>
{
new Item {Id = 1, Name = "John"},
new Item {Id = 2, Name = "Eric"},
};
GridView1.DataBind();
}
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "wView")
{
var imageButton = e.CommandSource as ImageButton;
string clientId = imageButton.ClientID;
int id = Convert.ToInt32(e.CommandArgument);
}
}
I am having trouble getting my dropdownlist to populate after I update the sqldatasource or change FormView Modes. The dropdown is created from an array in the code behind. I will post the snips of code below. The dropdown binds as expected until these events.
Any assistance in why this does not work would be awesome.
<asp:FormView ID="FormView1" runat="server" DataKeyNames="ID" DataSourceID="tbl_PreRegistration"
Width="100%" CssClass="c2wForm" DefaultMode="Edit">
<EditItemTemplate>
<asp:DropDownList ID="stateDDL" runat="server" OnSelectedIndexChanged="State_DDL_SelectedIndexChanged"
CausesValidation="false" AutoPostBack="true">
</asp:DropDownList>
<asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
Text="Update" CssClass="button blue" />
<asp:LinkButton ID="btnReset" runat="server" CausesValidation="False"
Text="Cancel" CssClass="button white" OnClick="btnReset1_Click" />
</ContentTemplate></asp:UpdatePanel>
</EditItemTemplate>
</asp:FormView>
CODE BEHIND:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
populateStateDDL("stateDDL", "CA");
}
}
protected void populateStateDDL(string DDL_ID, string getCurrentValue)
{
DropDownList strDDL_ID = (DropDownList)FormView1.FindControl(DDL_ID);
ArrayList states = new ArrayList();
strDDL_ID.DataValueField = "Value";
strDDL_ID.DataTextField = "Text";
strDDL_ID.DataSource = formating.GetAllStates();
strDDL_ID.DataBind();
strDDL_ID.SelectedValue = getCurrentValue.ToUpper();
}
you need to create the control every time, not just when postback = false. the control should be rendered in the Init event so that it can then be wired into viewstate and all that other webforms stuff.
here is some pseudo-code
private DropDownList ctrl;
protected override void Init(EventArgs e)
{
base.Init(e);
ctrl = new DropDownList
{
Id = "name of control",
DataValueField = "Value",
DataTextField = "Text"
};
Controls.Add(ctrl);
}
protected override void Load(EventArgs e)
{
base.Load(e);
if(ispostback) return;
ctrl.DataSource = GetData();
DataBind();
}
I have a GridView with a TemplateField column that I put PlaceHolder controls in. During the DataBound event for the GridView I dynamically add a few CheckBoxes to the PlaceHolder. That works fine and displays as expected.
My problem is that during the RowUpdating event the PlaceHolder contains no controls; my CheckBoxes are missing. I also noticed that they're missing during the RowEditing event.
I want to be able to get the values of the CheckBoxes during the RowUpdating event so I can save them to the database.
Here's some example code. I've trimmed out a lot to reduce size, but if you want to see specifics just ask and I'll be happy to add more.
HTML:
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False"
ondatabound="gridView_DataBound" onrowupdating="gridView_RowUpdating"
onrowediting="gridView_RowEditing" DataKeyNames="ID">
<Columns>
<asp:TemplateField HeaderText="Countries">
<ItemTemplate>
<asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
</ItemTemplate>
<EditItemTemplate>
<asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="editButton" runat="server" CommandName="Edit" Text="Edit"></asp:LinkButton>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="updateButton" runat="server" CommandName="Update" Text="Update"></asp:LinkButton>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code behind:
// This method works fine, no obvious problems here.
protected void gridView_DataBound(object sender, EventArgs e)
{
// Loop through the Holidays that are bound to the GridView
var holidays = (IEnumerable<Holiday>)gridView.DataSource;
for (int i = 0; i < holidays.Count(); i++)
{
// Get the row the Holiday is bound to
GridViewRow row = gridView.Rows[i];
// Get the PlaceHolder control
var placeHolder = (PlaceHolder)row.FindControl("countriesPlaceHolder");
// Create a CheckBox for each country and add it to the PlaceHolder
foreach (Country country in this.Countries)
{
bool isChecked = holidays.ElementAt(i).Countries.Any(item => item.ID == country.ID);
var countryCheckBox = new CheckBox
{
Checked = isChecked,
ID = country.Abbreviation + "CheckBox",
Text = country.Abbreviation
};
placeHolder.Controls.Add(countryCheckBox);
}
}
}
protected void gridView_RowEditing(object sender, GridViewEditEventArgs e)
{
// EXAMPLE: I'm expecting checkBoxControls to contain my CheckBoxes, but it's empty.
var checkBoxControls = gridView.Rows[e.NewEditIndex].FindControl("countriesPlaceHolder").Controls;
gridView.EditIndex = e.NewEditIndex;
BindData();
}
protected void gridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
// EXAMPLE: I'm expecting checkBoxControls to contain my CheckBoxes, but it's empty.
var checkBoxControls = ((PlaceHolder)gridView.Rows[e.RowIndex].FindControl("countriesPlaceHolder")).Controls;
// This is where I'd grab the values from the controls, create an entity, and save the entity to the database.
gridView.EditIndex = -1;
BindData();
}
This is the article that I followed for my data binding approach: http://www.aarongoldenthal.com/post/2009/04/19/Manually-Databinding-a-GridView.aspx
You need to call your BindData() method on page load.
"Dynamic controls or columns need to be recreated on every page load, because of the way that controls work. Dynamic controls do not get retained so you have to reload them on every page postback; however, viewstate will be retained for these controls."
See Cells in gridview lose controls on RowUpdating event
Also in the article you linked, there is an ItemTemplate and an EditItemTemplace because they have different displays, i.e. read only and editable. Yours are the same so I think you could simplify your design:
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" ondatabound="gridView_DataBound">
<Columns>
<asp:TemplateField HeaderText="Countries">
<ItemTemplate>
<asp:PlaceHolder ID="countriesPlaceHolder" runat="server"></asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<asp:LinkButton ID="editButton" runat="server" Text="Edit" onclick="editButton_Click" ></asp:LinkButton>
<asp:LinkButton ID="updateButton" runat="server" Text="Update" onclick="updateButton_Click" ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code Behind:
protected void gridView_DataBound(object sender, EventArgs e)
{
// Loop through the Holidays that are bound to the GridView
var holidays = (IEnumerable<Holiday>)gridView.DataSource;
for (int i = 0; i < holidays.Count(); i++)
{
// Get the row the Holiday is bound to
GridViewRow row = gridView.Rows[i];
// Get the PlaceHolder control
var placeHolder = (PlaceHolder) row.FindControl("countriesPlaceHolder");
var countryCheckBox = new CheckBox
{
Checked = true,
ID = "auCheckBox",
Text = "Aus",
Enabled = false
};
placeHolder.Controls.Add(countryCheckBox);
var editButton = (LinkButton)row.FindControl("editButton");
editButton.CommandArgument = i.ToString();
var updateButton = (LinkButton)row.FindControl("updateButton");
updateButton.CommandArgument = i.ToString();
updateButton.Visible = false;
}
}
protected void editButton_Click(object sender, EventArgs e)
{
LinkButton editButton = (LinkButton) sender;
int index = Convert.ToInt32(editButton.CommandArgument);
GridViewRow row = gridView.Rows[index];
// Get the PlaceHolder control
LinkButton updateButton = (LinkButton)row.FindControl("updateButton");
updateButton.Visible = true;
editButton.Visible = false;
CheckBox checkbox = (CheckBox)row.FindControl("auCheckBox");
if (checkbox != null)
{
checkbox.Enabled = true;
// Get value and update
}
}
protected void updateButton_Click(object sender, EventArgs e)
{
LinkButton updateButton = (LinkButton)sender;
int index = Convert.ToInt32(updateButton.CommandArgument);
GridViewRow row = gridView.Rows[index];
// Get the PlaceHolder control
LinkButton editButton = (LinkButton)row.FindControl("updateButton");
editButton.Visible = true;
updateButton.Visible = false;
CheckBox checkbox = (CheckBox)row.FindControl("auCheckBox");
if (checkbox != null)
{
// Get value and update
checkbox.Enabled = false;
}
}
If you want to be it enabled from the get go, just remove the enabled checks and you can delete your edit button.
Hope that helps.