I'm pretty new to C# and asp.net so apologies if this is a really stupid question.
I'm using a grid view to display a number of records from a database.
Each row has an Edit Button. When the button is clicked I want an ID to be passed back to a function in my .cs file. How do I bind the rowID to the Button field?
I've tired using a hyper link instead but this doesn't seem to work because I'm posting back to the same page which already has a Permanter on the URL.
asp.net
<asp:GridView ID="gvAddresses" runat="server" onrowcommand="Edit_Row">
<Columns>
<asp:ButtonField runat="server" ButtonType="Button" Text="Edit">
</Columns>
</asp:GridView>
c#
int ImplantID = Convert.ToInt32(Request.QueryString["ImplantID"]);
Session.Add("ImplantID", ImplantID);
List<GetImplantDetails> DataObject = ImplantDetails(ImplantID);
System.Data.DataSet DSImplant = new DataSet();
System.Data.DataTable DTImplant = new DataTable("Implant");
DSImplant.Tables.Add(DTImplant);
DataColumn ColPostCode = new DataColumn();
ColPostCode.ColumnName = "PostCode";
ColPostCode.DataType = typeof(string);
DTImplant.Columns.Add(ColPostCode);
DataColumn ColConsigneeName = new DataColumn();
ColConsigneeName.ColumnName = "Consignee Name";
ColConsigneeName.DataType = typeof(string);
DTImplant.Columns.Add(ColConsigneeName);
DataColumn ColIsPrimaryAddress = new DataColumn();
ColIsPrimaryAddress.ColumnName = "Primary";
ColIsPrimaryAddress.DataType = typeof(int);
DTImplant.Columns.Add(ColIsPrimaryAddress);
DataColumn ColImplantCustomerDetailsID = new DataColumn();
ColImplantCustomerDetailsID.ColumnName = "Implant ID";
ColImplantCustomerDetailsID.DataType = typeof(int);
DTImplant.Columns.Add(ColImplantCustomerDetailsID);
foreach (GetImplantDetails Object in DataObject)
{
DataRow DRImplant = DTImplant.NewRow();
DRImplant["PostCode"] = Object.GetPostCode();
DRImplant["Consignee Name"] = Object.GetConsigneeName();
DRImplant["Primary"] = Object.GetIsPrimaryAddress();
DRImplant["Implant ID"] = Object.GeTImplantCustomerDetailsID();
DTImplant.Rows.Add(DRImplant); <--- this is what I need to be added to the button
}
gvAddresses.DataSource = DTImplant;
gvAddresses.DataBind();
In your Edit_Row method you can access the index of the row you are editing like:
int rowIndex = (int)e.CommandArgument;
Once you have that you can access the row directly and pull out any values you want:
GridViewRow row = gvTest.Rows[rowIndex];
int implantId = Int32.Parse(string row.Cells[3].Text);
Alternatively, you can also add the property DataKeyNames="Implant ID" to your GridView and access the id that way:
int implantId = Int32.Parse(gvTest.DataKeys[rowIndex]["Implant ID"].ToString());
Related
I want to create a DataGridview to load few records after user performs a search in database once user clicks on row it should show all records in TextBoxes.
I have more than 20 TextBoxes and few Comboboxes and a DateTimePicker but I just want to show few columns in the DataGridView.
I know how to load data into a DataGridView on form load, but on search or on row click select all DataGridView Column into TextBoxes I am stuck.
Per your comment, here is how to change data on row changing in a datagridview. you will need to alter this to make the actual database calls. I made a small table for example purposes. For this to work, make a new winforms application, put a DataGridView on it and 2 textboxes
using System.Data;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
DataTable PretendImADataBase;
public Form1()
{
InitializeComponent();
PretendImADataBase = CreateTestData();
//this assigns the row enter event to this function. Each time the row changes,
//the function is called. Inside this function, you load your "big data" columns.
//That way, you only load 2 or 3 columns for all rows, and each time the row changes,
//you go back out and load all of the details for only that 1 row.
//Pretty basic way to load data..
dataGridView1.RowEnter += dataGridView1_RowEnter;
//initial loading, only 1 or 2 columns of large dataset, to keep loading time fast.
//primary key, and enough info to identify the full record.
dataGridView1.DataSource = CreateDataSource1();
}
private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e)
{
//This is where you would make your database call to load big data.
var x = sender as DataGridView;
if (x.DataSource == null) return;
var id = x[0, e.RowIndex].Value;
DataRow oRow = (from DataRow row in PretendImADataBase.Rows where (int)row["FK"] == (int)id select row).FirstOrDefault();
if (!(oRow == null))
{
textBox1.Text = oRow[3].ToString();
textBox2.Text = oRow[4].ToString();
}
}
private DataTable CreateTestData()
{
DataTable oDt = new DataTable();
DataColumn oCol = new DataColumn("ID", typeof(int));
oDt.Columns.Add(oCol);
oCol = new DataColumn("FK", typeof(int));
oDt.Columns.Add(oCol);
oCol = new DataColumn("Data1", typeof(string));
oDt.Columns.Add(oCol);
oCol = new DataColumn("Data2", typeof(string));
oDt.Columns.Add(oCol);
DataRow oRow = oDt.NewRow();
oRow["ID"] = 1;
oRow["FK"] = 1;
oRow["Data1"] = "Test Data 1";
oRow["Data2"] = "Test Data 2";
oDt.Rows.Add(oRow);
oRow = oDt.NewRow();
oRow["ID"] = 2;
oRow["FK"] = 2;
oRow["Data1"] = "Test Data 3";
oRow["Data2"] = "Test Data 4";
oDt.Rows.Add(oRow);
return oDt;
}
private DataTable CreateDataSource1()
{
DataTable oDt = new DataTable();
DataColumn oCol = new DataColumn("ID",typeof(int));
oDt.Columns.Add(oCol);
oCol = new DataColumn("Display", typeof(string));
oDt.Columns.Add(oCol);
DataRow oRow = oDt.NewRow();
oRow["ID"] = 1;
oRow["Display"] = "Test 1";
oDt.Rows.Add(oRow);
oRow = oDt.NewRow();
oRow["ID"] = 2;
oRow["Display"] = "Test 2";
oDt.Rows.Add(oRow);
return oDt;
}
}
}
Not really sure if I get what you want but, you are using the datasource of the datagridview to bind the results, right? if so, after you selected the datasourse, you can hide the columns you dont want to show, like this:
DataGridView dgv = new DataGridView();
dgv.DataSource = YourDataTable;
// hide the columns you dont want on grid
dgv.Columns[0].Visible = false;
dgv.Columns[2].Visible = false;
dgv.Columns[3].Visible = false;
dgv.Columns[4].Visible = false;
This way your grid will show only the columns you want, but when the click event triggers you can access the hidden columns to show them on your controls.
You can do this simple task.
You have to add all the columns in your GridView as the text fields you have on your form.
You can set the Visible property of the column to true that you want to show otherwise you can hide by setting this property to false.
Now, you will be able to fill the row data to the relevant fields on the form using CellDoubleClick or CellClick or RowDoubleClick or RowClick events.
You have to set the property of grid view AutoGenerateColumns to False and the name of each data table column name is to map with grid view columns using DataGridViewProperty.
I Created a application which will map the data and save the Data fields. For that first row in my GridView I added new HearerRow with dropdownlist.
Below is my code which I have attached.
My HTML Page code:
<asp:GridView ID="gvDataMapping" runat="server" AutoGenerateColumns="false">
</asp:GridView>
And Code Behind:
for (int i = 0; i < dtValues.Columns.Count; i++)
{
BoundField boundfield = new BoundField();
boundfield.DataField = dtValues.Columns[i].ColumnName.ToString();
boundfield.HeaderText = dtValues.Columns[i].ColumnName.ToString();
gvDataMapping.Columns.Add(boundfield);
}
gvDataMapping.DataSource = dtValues;
gvDataMapping.DataBind();
GridViewRow HeaderGridRow = new GridViewRow(0, 0, DataControlRowType.Header,
DataControlRowState.Insert);
DropDownList ddlFieldValues;
TableCell HeaderCell;
foreach (DataColumn dc in dtValues.Columns)
{
ddlFieldValues = new DropDownList();
ddlFieldValues.ID = "FieldValues";
ddlFieldValues.DataSource = (DataTable)Session["WorkItemTypeField"];
ddlFieldValues.DataTextField = "FieldName";
ddlFieldValues.DataValueField = "FieldID";
ddlFieldValues.DataBind();
ddlFieldValues.Items.Insert(0, new ListItem("", "0"));
HeaderCell = new TableCell();
HeaderCell.Controls.Add(ddlFieldValues);
HeaderGridRow.Cells.Add(HeaderCell);
}
gvDataMapping.DataSource = dtValues;
gvDataMapping.DataBind();
gvDataMapping.Visible = true;
lblDataMapping.Visible = true;
gvDataMapping.Controls[0].Controls.AddAt(1, HeaderGridRow);
See the Click here to view screen displays the output of above code . While clicking Save am not getting the GridView Header DropDowmList its showing null using below code.
GridViewRow gvrow2 = gvDataMapping.HeaderRow;
foreach (GridViewRow row in gvDataMapping.Rows)
{
for (int i = 0; i < gvDataMapping.Columns.Count; i++)
{
String header = gvDataMapping.Columns[i].HeaderText; //gets column name
DropDownList cellText = ((DropDownList)gvrow2.Cells[i].FindControl("FieldValues")); //Not getting the DDL returns null
}
}
How to get the GridView Header row dropdownlist values in Save click event?
No guarantees, because I haven't tried this myself, but what about this code?
GridViewRow gvrow1 = GrdDynamic1.HeaderRow;
foreach (GridViewRow row in GrdDynamic1.Rows)
{
for (int i = 0; i < GrdDynamic1.Columns.Count; i++)
{
String header = GrdDynamic1.Columns[i].HeaderText;
DropDownList cellText = ((DropDownList)gvrow1.Cells[i].FindControl("FieldValues"));
}
}
It looks as if you're looking for the drop down list in the right column, but not the right row: you're looking in the data row, rather than the header row gvrow1.
I am trying to make a column a hyperlink in my grid view. I am Using Umbraco 6 childpages as datasource. I have a link but at the moment it's going to /website/masterpages/url with %20% in the spaces
My View is like this:
<asp:hyperlinkfield datatextfield="title" datanavigateurlfields="title" headertext="Title" />
and code behind like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
HyperLinkField title = new HyperLinkField();
string[] dataNavigateUrlFields = { "title" };
title.DataTextField = "title";
title.DataNavigateUrlFields = dataNavigateUrlFields;
title.HeaderText = "Title";
title.DataNavigateUrlFormatString = "item.Url";
// Create a BoundField object to display the company's city.
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[3] { new DataColumn("title", typeof(String)),
new DataColumn("lastUpdated", typeof(string)),
new DataColumn("theme",typeof(string)) });
int i = 0;
foreach (var item in uQuery.GetCurrentNode().ChildrenAsList)
{
var dateTimeString = item.GetProperty("lastUpdated").Value.ToString();
var dateTime = System.Xml.XmlConvert.ToDateTime(dateTimeString);
dt.Rows.Add(item.Name, dateTime.ToString("dd.MM.yyyy"), item.GetProperty("theme").Value.ToString());
}
Session["data"] = dt;
Cache["Data"] = dt;
Practice.DataSource = dt;
Practice.DataBind();
}
can anyone tell me what I'm doing wrong - thanks
I figured it out, but adding an extra column to the table called name (as this is not displayed unless you reference it on the output, removing:
HyperLinkField title = new HyperLinkField();
string[] dataNavigateUrlFields = { "title" };
title.DataTextField = "title";
title.DataNavigateUrlFields = dataNavigateUrlFields;
title.HeaderText = "Title";
title.DataNavigateUrlFormatString = "item.Url";
// Create a BoundField object to display the company's city.
and changing the datatextfield to "name" ie DataTextField="name".
If anyone else gets stuck:)
I'm creating dynamically data table bound to Grid View. Every row is populated with button. When I determine which button is clicked on the row, I want to get the current value of cell in that row modify her.
Markup:
<asp:GridView ID="GridView2" runat="server"
OnRowDataBound="GridView2_RowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnTest" runat="server"
CommandName="odzemi"
CssClass="button2"
Font-Bold="True"
Text="-"
Width="100px"
OnClick="btnTest_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
Creating the row:
private void AddNewRecordRowToGrid()
{
int counter;
if (Request.Cookies["kasa"] == null)
counter = 0;
else
{
counter = int.Parse(Request.Cookies["kasa"].Value);
}
counter++;
Response.Cookies["kasa"].Value = counter.ToString();
Response.Cookies["kasa"].Expires = DateTime.Now.AddYears(2);
if (ViewState["Markici"] != null)
{
DataTable dtCurrentTable = (DataTable)ViewState["Markici"];
DataRow drCurrentRow = null;
if (dtCurrentTable.Rows.Count > 0)
{
for (int i = 1; i <= dtCurrentTable.Rows.Count; i++)
{
HttpCookie cookie = Request.Cookies["Democookie"];
drCurrentRow = dtCurrentTable.NewRow();
drCurrentRow["FirmaID"] = Request.Cookies["firma"].Value;
drCurrentRow["Godina"] = Request.Cookies["godina"].Value;
drCurrentRow["KasaID"] = Request.Cookies["kasa"].Value;
drCurrentRow["MarkicaID"] = Request.Cookies["kasa"].Value;
drCurrentRow["Datum"] = DateTime.Now;
drCurrentRow["Masa"] = Session["masa39"];
drCurrentRow["VrabotenID"] = Session["New"];
drCurrentRow["Artikal"] = Label3.Text;
drCurrentRow["Cena1"] = Label4.Text;
//this is where i need to make changes
drCurrentRow["Kolicina"] = Label5.text;
drCurrentRow["Smena"] = Session["smena1"];
drCurrentRow["VkIznos"] = Label6.Text;
drCurrentRow["VkDanok"] = Label8.Text;
drCurrentRow["SySDatum"] = DateTime.Now;
drCurrentRow["Vid"] = Label23.Text;
drCurrentRow["Edmera"] = Label10.Text;
drCurrentRow["ArtikalID"] = Label33.Text;
}
//Removing initial blank row
if (dtCurrentTable.Rows[0][0].ToString() == "")
{
dtCurrentTable.Rows[0].Delete();
dtCurrentTable.AcceptChanges();
}
//Added New Record to the DataTable
dtCurrentTable.Rows.InsertAt(drCurrentRow,0);
//storing DataTable to ViewState
ViewState["Markici"] = dtCurrentTable;
//binding Gridview with New Row
GridView2.DataSource = dtCurrentTable;
GridView2.DataBind();
}
}
}
//determine which button is clicked in data Table
//and here
protected void btnTest_Click(object sender, EventArgs e)
{
DataTable dtCurrentTable = (DataTable)ViewState["Markici"];
var clickedRow = ((Button)sender).NamingContainer as GridViewRow;
var clickedIndex = clickedRow.RowIndex;
count--;
decimal noofcount = count;
//and here i want to get current value and modify her.
dtCurrentTable.Rows[clickedIndex]["Kolicina"] = "88";
GridView2.DataSource = dtCurrentTable;
GridView2.DataBind();
}
If the only problem is that you don't know how to read the old value as noted here:
//and here i want to get current value and modify her.
dtCurrentTable.Rows[clickedIndex]["Kolicina"] = "88";
then this works:
object oldValue = dtCurrentTable.Rows[clickedIndex]["Kolicina"];
// cast/convert it to whatever it is
or (what i prefer):
string old = dtCurrentTable.Rows[clickedIndex].Field<string>("Kolicina");
int oldValue = int.Parse(old); // in case that you don't know
int newValue = oldValue + count; // just an example
dtCurrentTable.Rows[clickedIndex].SetField("Kolicina", newValue.ToString());
I'm using the Field/SetField extension methods for DataRow because it is strongly typed and even supports nullable types.
By the way, why do you store ints as strings?
I am trying to learn how to join two data tables into one using Linq. My linq query is working correctly and I can see expected values in it. However, when I loop the linq results, and assign the values to a newly created data row and add that row to a new data table, the rows come out empty.
Here is my code:
private void btnCombine_Click(object sender, EventArgs e)
{
var innerJoinQuery =
from strRow in StrDataTable.AsEnumerable()
join intRow in IntDataTable.AsEnumerable()
on strRow.Field<int>("IntID") equals intRow.Field<int>("ID")
select new {
IntOne = intRow.Field<int>("FirstNum"),
IntTwo = intRow.Field<int>("SecondNum"),
StrOne = strRow.Field<string>("FirstStr"),
StrTwo = strRow.Field<string>("SecondStr"),
StrThree = strRow.Field<string>("SecondStr")
};
DataTable newTable = new DataTable();
newTable.Columns.Add("IntOne");
newTable.Columns.Add("IntTwo");
newTable.Columns.Add("FirstStr");
newTable.Columns.Add("SecondStr");
newTable.Columns.Add("ThirdStr");
newTable.Columns["IntOne"].DataType = System.Type.GetType("System.String");
newTable.Columns["IntTwo"].DataType = System.Type.GetType("System.String");
newTable.Columns["FirstStr"].DataType = System.Type.GetType("System.String");
newTable.Columns["SecondStr"].DataType = System.Type.GetType("System.String");
newTable.Columns["ThirdStr"].DataType = System.Type.GetType("System.String");
foreach (var row in innerJoinQuery)
{
DataRow rowToAdd = newTable.NewRow();
rowToAdd.ItemArray[0] = row.IntOne.ToString();
rowToAdd.ItemArray[1] = row.IntTwo.ToString();
rowToAdd.ItemArray[2] = row.StrOne.ToString();
rowToAdd.ItemArray[3] = row.StrTwo.ToString();
rowToAdd.ItemArray[4] = row.StrThree.ToString();
newTable.Rows.Add(rowToAdd);
}
dataGridView3.DataSource = newTable;
}
Using DataRow.ItemArray property with individual values doesn't work - instead, create the object[] array and then set the whole thing to the .ItemArray property. See this MSDN page for additional examples.
foreach (var row in innerJoinQuery)
{
DataRow rowToAdd = newTable.NewRow();
object[] items = new object[] {
row.IntOne.ToString(),
row.IntTwo.ToString(),
row.StrOne.ToString(),
row.StrTwo.ToString(),
row.StrThree.ToString()
};
rowToAdd.ItemArray = items;
newTable.Rows.Add(rowToAdd);
}
Alternately, use the DataRow indexer directly, which works with individual columns:
rowToAdd[0] = row.IntOne.ToString();
rowToAdd[1] = row.IntTwo.ToString();
rowToAdd[2] = row.StrOne.ToString();
rowToAdd[3] = row.StrTwo.ToString();
rowToAdd[4] = row.StrThree.ToString();
Additionally, when creating columns, there is a constructor that takes the type which can save you some code. Your first two column types are mismatched.
newTable.Columns.Add("IntOne", typeof(int));
newTable.Columns.Add("FirstStr", typeof(string));
The first two values appear to be Integers:
IntOne = intRow.Field<int>("FirstNum"),
IntTwo = intRow.Field<int>("SecondNum"),
But the DataType you assign the columns to is String:
newTable.Columns["IntOne"].DataType = System.Type.GetType("System.String");
newTable.Columns["IntTwo"].DataType = System.Type.GetType("System.String");
Update those to int's and see if that resolves it:
newTable.Columns["IntOne"].DataType = System.Type.GetType("System.Int32");
newTable.Columns["IntTwo"].DataType = System.Type.GetType("System.Int32");
rowToAdd.ItemArray[0] = row.IntOne;
rowToAdd.ItemArray[1] = row.IntTwo;
You may also need to supply the DataPropertyName for the columns:
newTable.Columns["IntOne"].DataPropertyName = "FirstNum";
newTable.Columns["IntTwo"].DataPropertyName = "SecondNum";
...
And ensure that the AutoGenerateColumns value is set to false
dataGridView3.AutoGenerateColumns = false;