ok so I have this ASP:Table which pulls its rows of info from a stored procedure query, only two columns but wish to add a third with a button for each row that when clicked will grab the information in the prior columns for use in another function.
not sure how the hell to code it though as the buttons are generated per row and how can I programme events for a unknown number of buttons there must be a way of doing It programmatically.
Table Header
Datacolumn1 Datacolumn2
a 2 Select
b 4 Select
e 9 Select
so when I press select on the second row it gives me string1=b string2=4
I imagine the code would look something like this (not likely but in a ideal world :D)
protected void select_row (eventargs as e)
{
string data1 = Row(e).cell(0).text
int data2 = Row(e).cell(1).text
}
For a grid like this
<asp:GridView ID="Grid1" runat="server" onrowcommand="Grid1_RowCommand" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Datacolumn1" HeaderText="Data column1" />
<asp:BoundField DataField="Datacolumn2" HeaderText="Data column2" />
<asp:TemplateField>
<ItemTemplate>
<asp:Button runat="server" CommandName="SelectIt" Text="Select" CommandArgument='<%# Eval("Datacolumn1") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Use RowCommand event
protected void Grid1_RowCommand(object sender, GridViewCommandEventArgs e)
{
var btn = (Button)e.CommandSource ;
if (e.CommandName == "SelectIt")
{
var Row =(GridViewRow) btn.NamingContainer;
var Datacolumn1 = Row.Cells[0].Text;
var Datacolumn2 = Row.Cells[1].Text;
btn.Text = "selected: " + Datacolumn1 + "," + Datacolumn2;
}
}
Related
I have this asp.net control:
<div class="field" style="text-align: center;">
<asp:GridView ID="gvTags" runat="server" AutoGenerateColumns = "false"
OnRowDataBound="OnRowDataBound" OnRowDeleting="OnRowDelete">
<Columns>
<asp:BoundField DataField="tagId" HeaderText="Id" />
<asp:BoundField DataField="name" HeaderText="<%$ Resources:Common, tlblTags %>" />
<asp:CommandField ShowDeleteButton="True" ButtonType="Button" />
</Columns>
</asp:GridView>
</div>
And I bind my datasource like this from a collection retrieved from database:
this.gvTags.DataSource = product.Tags;
this.gvTags.DataBind();
In the OnRowDataBound I create a popup to show up when the delete button is clicked, so the code is this:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string item = e.Row.Cells[1].Text;
foreach (Button button in e.Row.Cells[2].Controls.OfType<Button>())
{
if (button.CommandName == "Delete")
{
button.Attributes["onclick"] = "if(!confirm('Do you want to delete " + item + "?')){ return false; };";
}
}
}
}
This is working fine, I can see the three rows in my browser and all works as expected (the popup is showing with the correct information etc). But the problem is when I accept the popup so the OnRowDelete event is fired.
I want to remove a Tag from the database with a specific tagId, so I need to get the position 0 at the current row, so this is my code to do that:
protected void OnRowDelete(object sender, GridViewDeleteEventArgs e)
{
int index = Convert.ToInt32(e.RowIndex);
GridViewRow row = this.gvTags.Rows[index];
long tagId = Convert.ToInt64(row.Cells[0].Text);
/* Remove the tag */
productService.RemoveTag(productId, tagId);
/* Delete the row from gridview */
this.gvTags.DeleteRow(index);
}
The error I'am getting is in this line: GridViewRow row = this.gvTags.Rows[index];. I'm getting System.ArgumentOutOfRangeException but I don't understand why. The index variable takes a valid int value like 0, 1...
Any ideas on what I'am doing wrong? Thanks.
My question is how can i insert values into gridviews rows.Basically I have created a gridview in which i bound the footer and i want to insert values in the footer.I have create a 'textboxs','dropdownlist' and 'checkboxes'.I want when i insert value and press "Insert" button then values shown in the gridview and again i insert value and press button then show inserted values in the gridview.Here is my gridview image
and i also want to edit and delete rows as well.Here is my code :
aspx code
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
Height="104px" ShowFooter="True" Width="463px"
AutoGenerateDeleteButton="True" AutoGenerateEditButton="True">
<Columns>
<asp:TemplateField HeaderText="Column Name">
<FooterTemplate>
<asp:TextBox ID="name" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Data Type">
<FooterTemplate>
<asp:DropDownList ID="DropDownList2" runat="server">
</asp:DropDownList>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Allow Null">
<FooterTemplate>
<asp:CheckBox ID="allow_null" runat="server" />
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Primary Key">
<FooterTemplate>
<asp:CheckBox ID="primary" runat="server" />
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
and here is my aspx.cs code :
protected void Button1_Click(object sender, EventArgs e)
{
string name = TextBox1.Text;
string type = DropDownList1.Text;
string allow=Null.Text;
string primary = Primary.Text;
name = ((TextBox)GridView1.FooterRow.FindControl("TextBox2")).Text;
type = ((DropDownList)GridView1.FooterRow.FindControl("DropDownList2")).Text;
allow = ((CheckBox)GridView1.FooterRow.FindControl("allow_null")).Text;
primary = ((CheckBox)GridView1.FooterRow.FindControl("primary")).Text;
}
To use the GridView in this way, with input fields in the footer and a Insert Button that is outside the GridView, you need to make a manual Insert.
I don't know how you perform an Insert using the EF model as I don't currently use it. I guess you could say the "old" way is to use an instance of SqlConnection and SqlCommand. You would use code similar to this inside your Button Click event:
// This is VB. C# is similar, you will have to convert where needed
Using connection As New SqlConnection(connectionString)
Using command As New SqlCommand(queryString, connection)
command.Connection.Open()
command.CommandType = // Typically Text or StoredProcedure as needed
command.Parameters.AddWithValue("#parameter_name1", some_value_1)
command.Parameters.AddWithValue("#parameter_name2", some_value_2)
.
.
.
command.ExecuteNonQuery()
End Using
End Using
queryString is your sql INSERT statement or a stored procedure
command.Parameters is a collection of replaceable parameter in your INSERT statement or Stored Proc.
Addendum
A Gridview is a Data bound control so typically when you use a gridview it's bound to some backing data source. If you are not using a database then you are using some other construct.
If you are using, for example, a DataTable, you would add the new rows and columns to the DataTable using its row and column methods and then rebind the DataTable to the Gridview. You don't add rows and columns directly to a GridView.
See this other SO answer by JonH for an example
In case this helps this is based on the ASPSnippets but modified to be more like you might need. Note that instead of using a DataTable I am using a List where "Row" is a class. It is somewhat a matter of personal preference which one you use. The "Row" class is:
[Serializable]
public class Row
{
public string FieldName { get; set; }
public string FieldType { get; set; }
public Boolean FieldNullible { get; set; }
public Boolean FieldPrimaryKey { get; set; }
}
My names are different from your names. Note that the ASPSnippets sample does not use TemplateFields so I am not. I am not sure if you need to make the "allow"
and/or "primary" fields Boolean so I did not process them in the form. So the ASP.Net form I have is:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
Height="104px" Width="463px"
AutoGenerateDeleteButton="True" AutoGenerateEditButton="True">
<Columns>
<asp:BoundField DataField="FieldName" HeaderText="Name" ItemStyle-Width="120" />
<asp:BoundField DataField="FieldType" HeaderText="Type" ItemStyle-Width="120" />
</Columns>
</asp:GridView>
<br /><asp:Label ID="Label1" runat="server" Text="Name:"></asp:Label>
<br /><asp:TextBox ID="txtName" runat="server" />
<br /><asp:Label ID="Label2" runat="server" Text="Type:"></asp:Label>
<br /><asp:TextBox ID="txtType" runat="server" />
<br /><asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="Insert" />
The code-behind is:
protected void Page_Load(object sender, EventArgs e)
{
if (this.IsPostBack)
return;
List<Row> Rows = new List<Row>();
ViewState["Rows"] = Rows;
BindGrid();
}
protected void BindGrid()
{
GridView1.DataSource = (List<Row>)ViewState["Rows"];
GridView1.DataBind();
}
protected void Insert(object sender, EventArgs e)
{
List<Row> Rows = (List < Row >)ViewState["Rows"];
Row r = new Row();
r.FieldName = txtName.Text.Trim();
r.FieldType = txtType.Text.Trim();
Rows.Add(r);
ViewState["Rows"] = Rows;
BindGrid();
txtName.Text = string.Empty;
txtType.Text = string.Empty;
}
One thing I do not like is that the GridView does not show until there is data in it. I assume you can fix that.
This does not implement the editing and deleting.
I have a GridView with some predefined Columns and some generated in code. The idea is that I show Columns according to category, selected by user. I cannot create all Columns and just hide them because I don't know how many Columns I will need. I manage to generate Columns I needed, but the problem starts when I try to remove generated Columns. Situation looks like this:
On first load I see GridView of all categories.
After clicking in ListBox I get result I want. 1 additional Column is created (RemoveAt is not called, because no additional Columns were yet created.).
After clicking in other ListBox Item I still get result I want. Column created last time where deleted and new Column added.
At this point, if I click any other ListBox Item in LicensesCategoriesListBox_SelectedIndexChanged on debugging I see that all of GridView TemplateFields are empty (http://tinypic.com/r/98vdkm/8).
If I comment section gridView.Columns.RemoveAt(i - 1) everything works fine, just Columns keeps generating and generating. Any ideas why all of my TemplateFields, written in my Page becomes empty?
My Page looks like this:
<asp:ListBox ID="licensesCategoriesListBox" runat="server" AutoPostBack="true" OnSelectedIndexChanged="LicensesCategoriesListBox_SelectedIndexChanged" />
<asp:GridView ID="licencesGridView" runat="server" AutoGenerateColumns="False" Caption="Licencijos" DataKeyNames="id" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="Pavadinimas">
<EditItemTemplate>
<asp:TextBox ID="licenceNameTextBox" runat="server" MaxLength="50" Text='<%# Bind("name") %>' />
</EditItemTemplate>
<FooterTemplate>
<asp:TextBox ID="newLicenceNameTextBox" runat="server" MaxLength="50" ToolTip="Pavadinimas" />
</FooterTemplate>
<ItemTemplate>
<span><%# Eval("name") %></span>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Kategorija">
<EditItemTemplate>
<asp:DropDownList ID="licenceCategoryDropDownList" runat="server" />
</EditItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="newLicenceCategoryDropDownList" runat="server" ToolTip="Kategorija">
<asp:ListItem Text="Pasirinkite kategorijÄ…:" />
</asp:DropDownList>
</FooterTemplate>
<ItemTemplate>
<span><%# Eval("category") %></span>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Code:
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
FillLicences(ref licencesGridView);
}
}
protected void LicensesCategoriesListBox_SelectedIndexChanged(object sender, EventArgs e) {
FillLicences(ref licencesGridView, licensesCategoriesListBox.SelectedValue); /// Value is ID of category.
}
public void FillLicences(ref GridView gridView, string category = "") {
DataTable dataTable;
ushort categoryId;
if (UInt16.TryParse(category, out categoryId)) {
PutAdditionalColumns(ref gridView, categoryId);
dataTable = sqlCommands.GetLicences(categoryId); /// Returns DataTable [name], [category] and additional fields that I add in PutAdditionalColumns method.
} else {
dataTable = sqlCommands.GetAllLicences(); /// Returns DataTable with only [name], [category]
}
gridView.DataSource = dataTable;
gridView.DataBind();
}
public void PutAdditionalColumns(ref GridView gridView, uint category) {
for (ushort i = (ushort)gridView.Columns.Count; i > 2; i--) { /// Removes columns at the end (created for other category)
gridView.Columns.RemoveAt(i - 1);
}
foreach (var pair in sqlCommands.GetLicencesCategoryAttributes(category)) { /// Takes additional field needed.
TemplateField field = new TemplateField(); /// New empty column.
field.AccessibleHeaderText = pair.Key.ToString();
field.HeaderText = pair.Value;
gridView.Columns.Add(field);
}
}
Any ideas why all of my TemplateFields, written in my Page becomes
empty?
Because each of those fields is considered a Column. You're removing them in the code.
If this is your issue, you need some way to seperate columns defined in the aspx to the ones created in the code.
I'd use DataColumn.ExtendedProperties to do this.
Whenever you add a column from code, add a value to ExtendedProperties, showing that it was created in the code.
//...
TemplateField field = new TemplateField(); /// New empty column.
field.AccessibleHeaderText = pair.Key.ToString();
field.HeaderText = pair.Value;
DataColumn ourNewColumn = gridView.Columns.Add(field);
ourNewColumn.ExtendedProperties.Add("CreatedInCode", true);
//...
And then when you come to delete them, only delete them if they have this property set.
//...
if( gridView.Columns[i - 1].ExtendedProperties.ContainsKey("CreatedInCode") ) {
gridView.Columns.RemoveAt(i - 1);
}
//...
Hi and thanks in advance.
I have a gridview that has four columns. The fourth column is hidden or displayed based on a set of criteria which is working correctly. But when the table displays, the very first cell in that last column is not showing any text, even though on databound it clearly shows that it has the text. So the gridview winds up showing data like this:
Name Address Zip Code
X H. Smith 123 Raton Ave.
X A. Rally 345 6th St 98453
X B. Holcomb 876 Harrison Blvd 56321
The OnRowDataBound looks like this:
protected void gvAddresses_OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//This test evaluation string showed the correct data for every row
//string myvalue = DataBinder.Eval(e.Row.DataItem, "ZipCode").ToString();
if (user.State == (int)States.California)
gvAddresses.Columns[3].Visible = true;
}
}
There doesn't seem to be any problem with the binding and when I debug through the gridview each row is processed as I would expect. Here is the gridview:
<asp:GridView runat="server" ID="gvAddresses" CssClass="TableFormat gvMargin" Width="100%" AutoGenerateColumns="false"
OnRowCommand="gvAddresses_OnRowCommand" OnRowDeleting="gvAddresses_OnRowDeleting" OnRowDataBound="gvAddresses_OnRowDataBound">
<EmptyDataTemplate>
<div style="text-align: center;">No addresses available.</div>
</EmptyDataTemplate>
<Columns>
<asp:TemplateField HeaderText="" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton ID="lnkRemoveAddress" runat="server" OnClientClick="if(!confirm('Are you sure you want to delete this record?')) return ;" style="color: maroon; font-weight: bold;" Text="X" CommandName="Delete" CommandArgument='<%# Eval("AddressCode") %>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="Address" HeaderText="Address" />
<asp:BoundField DataField="ZipCode" HeaderText="Zip Code" Visible="False"/>
</Columns>
</asp:GridView>
How else can I discover what is happening to this first cell?
First problem is this: you are checking every individual row and setting the entire column to visible or not over and again. You should check for State before you databind, since it is the user object I would suggest doing it on preinit.
I suggest you remove the visible=false from your markup. When you set visible to false then the control/object isn't rendered into the HTML. Your problem will most likely be fixed if you remove the visibility attribute from the markup and assign that value at the proper time in codebehind.
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
if (!postback)
{
gvAddresses.Columns[3].Visible = User.State == (int)States.California;
}
}
I'm just at a function, which outputs a list of file names from the database. I get this also from the database and store it into a DataTable. The DataTable give the list to a DataGrid, which displays it on the page. That works fine.
My problem is that I want next to each file name have a check box on the right, which I can tick and Next time when I save the form, the database entry will be deleted.
How can I do this so the program dynamically displays the checkbox to the DataTable and the checkbox would know to which entry it has?
Best Regards
Michael Ryter
<asp:TemplateField HeaderText="name" SortExpression="Name">
<ItemTemplate>
<asp:Checkbox id="chkIsDeletable" runat="server" />
<asp:HiddenField id="hndFileId" runat="server" Value='<%#Eval("FileID")%>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="name" SortExpression="Name">
<ItemTemplate>
<%#Eval("filename") %>
</ItemTemplate>
</asp:TemplateField>
Now on button click event:
protected void Button_Click(object sender, EventArgs e)
{
String SelectedFileIds ="";
foreach (GridViewRow item in GridView1.Rows)
{
CheckBox chkIsDeletable = item.FindControl("chkIsDeletable") as CheckBox;
HiddenField hndFileId = item.FindControl("hndFileId") as HiddenField;
if (chkIsDeletable.Checked)
SelectedFileIds = hndFileId.Value + ",";
}
SelectedFileIds = SelectedFileIds.TrimEnd(",");
}
Now you will have all those file ids for which you have ticked the checbox, now you can delete those records from the database which contains selected fileids.
Hope, it will help you!!!