I have an ASP.Net gridview which is binding properly.On edit i am editing certain fields.then after i need to edit other rows as well.But when i am trying to edit other rows the previously edited rows get reset n retain their older values.
The requirement is as such that i have to edit many rows and the on a button click i need to push all the edit values to the database
You need to maintain your GridView's datasource between postbacks.
You can do this by storing your DataTable in Cache, Session, or any persistent storage.
Upon edit of a row, save the changes to this DataTable, then rebind the Gridview (from this DataTable).
When the user clicks "save all", you can save the changed rows of the DataTable to the database.
If you need to keep track of which rows have changed, you can maintain a list of PrimaryKeys that have changed in cache or Session.
Are you checking !IsPostBack inside Page_Load event before binding the grid? If you are not binding the grid in Page_Load event, please post the code to bind the grid.
The problem with your code is,you r binding grid on page load.. so when page is loading , it can bind the values which are in database. for that write bind method on Post back and also maintain your values on sessions or Hidden Fields,when you click on save button update database with that sessions or hidden fields..
morning bryan...here is that code for getting the value from the gridview to the datatable
private void getGridInfo()
{
DataTable dt = new DataTable();
DataRow dr;
dt.Columns.Add(new System.Data.DataColumn("Select", typeof(byte)));
dt.Columns.Add(new System.Data.DataColumn("Client", typeof(string)));
dt.Columns.Add(new System.Data.DataColumn("PrincipleAmt", typeof(double)));
foreach (GridViewRow row in grdRepayment.Rows)
{
CheckBox Select = (CheckBox)row.FindControl("ChkSelect");
Label ClientName = (Label)row.FindControl("lblClientName");
Label Principal = (Label)row.FindControl("lblPricipal");
dr = dt.NewRow();
dr[0] = Convert.ToByte(Select.Checked);
dr[1] = ClientName.Text;
dr[2] = Convert.ToDouble(Principal.Text);
dt.Rows.Add(dr);
}
Session["TempTable"] = dt;
}
now here is the code for updating that session variable which holds the datatable,this must be done in RowUpdating Event of the Gridview.
protected void grdRepayment_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
DataTable myDatatable;
GridViewRow row = grdRepayment.Rows[e.RowIndex];
grdRepayment.EditIndex = -1;
if (row != null)
{
myDatatable = (DataTable)Session["TempTable"];
for (int i = 0; i < myDatatable.Rows.Count; i++)
{
if (e.RowIndex == i)
{
myDatatable.Rows[i][1] = Convert.ToString(Client);
myDatatable.Rows[i][2] = Convert.ToString(Principal);
Session["TempTable"] = myDatatable;
grdRepayment.EditIndex = -1;
grdRepayment.DataSource = myDatatable;
grdRepayment.DataBind();
}
}
}
}
and make sure you bind the grid from this session variable only in RowEditing and RowCancellingEdit Events.
Once you are done with the Editing thing simply click the button which will push the edited content to the DATABASE...
Please check you'r gridview binding method was call page load and inside of !isPostBack?
for
Void page_load()
{
if(!IsPostBack)
{
//Call GridView Binding method
}
}
protected void grdRepayment_RowEditing(object sender, GridViewEditEventArgs e)
{
grdRepayment.EditIndex = e.NewEditIndex;
myDatatable = (DataTable)Session["TempTable"];
grdRepayment.DataSource = myDatatable;
grdRepayment.DataBind();
}
This is how we need to Bind the grid in RowEditing and RowCancelingEdit
Related
I have 2 datagrid views with one datatable. I am trying to have a button that when clicked it adds the rows from csv_datagridview to optimal_datagridview. The below works however whenever I deselect an entry in csv_datagridview and hit the button again it clears that selection. I would like to have the selection stick each time.
if (selectedRowCount <= 9)
{
List<object> destList = new List<object>();
foreach (DataGridViewRow row in csv_datagridview.SelectedRows)
destList.Add(row.DataBoundItem);
optimaldataGridView.DataSource = destList;
Thank you so much in advance :)
It is unclear what your exact problem is with the little code you show, but from your statement whenever I deselect an entry in csv_datagridview and hit the button again it clears that selection. I am guessing that if nothing is selected, the data in optimaldataGridView clears when you press the add selected button.
I will assume the csv_datagridview is bound to a table. Your posted code shows the creation of new List destList which you fill with the selected rows from the csv_datagridview. Then you set optimaldataGridView data source to the destList. One issue I see in this picture is that as soon as you leave the if (selectedRowCount <= 9) clause… destList will no longer exist. As a data source for a DataGridView on your form, I would think you would want to keep this List global as long as the form is open. Either way... you are not adding the selected rows, you are simply removing the existing rows and then adding what was selected in csv_datagridview.
I hope the code below will help. I created two DataTables, one for each DataGridView. The csv_datagridview data table is filled with some data, the second data table is left empty. Then simply add the selected rows from the csv_datagridview to the optimaldataGridView’s DataTable… Then refresh optimaldataGridView.
DataTable table1;
DataTable table2;
public Form1() {
InitializeComponent();
csv_datagridview.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
optimaldataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
table1 = GetTable("table1");
table2 = GetTable("table2");
FillTable(table1);
csv_datagridview.DataSource = table1;
optimaldataGridView.DataSource = table2;
}
private void button1_Click(object sender, EventArgs e) {
if (csv_datagridview.SelectedRows.Count > 0) {
foreach (DataGridViewRow row in csv_datagridview.SelectedRows) {
DataRowView dr = (DataRowView)row.DataBoundItem;
table2.Rows.Add(dr.Row.ItemArray[0], dr.Row.ItemArray[1], dr.Row.ItemArray[2]);
}
optimaldataGridView.Refresh();
}
}
private DataTable GetTable(string name) {
DataTable table = new DataTable(name);
table.Columns.Add("col1");
table.Columns.Add("col2");
table.Columns.Add("col3");
return table;
}
private void FillTable(DataTable table) {
for (int i = 0; i < 10; i++) {
table.Rows.Add("R" + i + "C0", "R" + i + "C1", "R" + i + "C2");
}
}
Hope this helps.
Your code is working on my side.
Created a DataTable for Datasource of csv_datagridview.
Selected some rows in this grid.
Clicked the button to copy the selected rows to the
optimaldataGridView
The selected rows are still selected.
public Form1()
{
InitializeComponent();
DataTable dt = new DataTable();
dt.ReadXml(Application.StartupPath + #"\test.xml");
csv_datagridview.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
csv_datagridview.DataSource = dt;
}
private void button1_Click(object sender, EventArgs e)
{
List<object> destList = new List<object>();
foreach (DataGridViewRow row in csv_datagridview.SelectedRows)
destList.Add(row.DataBoundItem);
optimaldataGridView.DataSource = destList;
}
Make sure you have no events attached to the grids that may affect the selection.
I am using this code to take a gridview count and display in a label on page load and works fine.
Page Load:
int rowCount = dtDetails.Rows.Count;
lblTotalRows.Text = rowCount.ToString() + "records found";
I have a dropdown above my gridview and when I select dropdown values the row count have to changed based on the dropdown selected values.
How could I possibly do that in dropdown selected index change
protected void ddlGroup_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtGroup = DataRepository.GetGroup(ddlGroup.Text);
gvDetails.DataSource = dtGroup;
gvDetails.DataBind();
//Now how could I possible show the respective row counts in the label
}
protected void ddlGroup_SelectedIndexChanged(object sender, EventArgs e)
{
DataTable dtDept = DataRepository.GetDept(ddlGroup.Text, ddlDept.Text);
gvDetails.DataSource = dtDept;
gvDetails.DataBind();
//Now how could I possible show the respective row counts of both group and
dept row count since they are cascading dropdowns in the label
}
Any suggestions?
I tend to make a SetData() method so all this kind of code is in one place. So in this instance I would:
protected void SetData(DataTable dtGroup)
{
// Bind the data to the grid
gvDetails.DataSource = dtGroup;
gvODetails.DataBind();
// Show row count
if (!dtGroup.Rows.Count.Equals(0))
lblTotalRows.Text = dtGroup.Rows.Count + " records found";
else
lblTotalRows.Text = "No records found";
}
This way you only have one place that does all the 'bindind' so in your Page_Load you can just call this SetData() method and pass in the datatable, and the same on your SelectedIndexChanged.
I want to update row in GridView with this code but after editing GridView not changes:
protected void res_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//Retrieve the table from the session object.
DataTable dt = (DataTable)Session["dt"];
GridViewRow row =res.Rows[e.RowIndex];
dt.Rows[row.DataItemIndex]["name"] = ((TextBox)(row.Cells[6].Controls[0])).Text;
dt.Rows[row.DataItemIndex]["dewey"] = ((TextBox)(row.Cells[5].Controls[0])).Text;
*dt.Rows[row.DataItemIndex]["subject"] = ((TextBox)(row.Cells[4].Controls[0])).Text;
Session["dt"] = dt;
res.EditIndex = -1;
res.DataSource = dt;
res.DataBind();
}
my Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
DataTable dt;
if (!IsPostBack)
{
dt= Converter.ListBooks(new classes.Book().GetAll());
Session["dt"] = dt;
res.DataSource = dt;
res.DataBind();
}
else
{
dt=(DataTable)Session["dt"];
res.DataSource = dt;
res.DataBind();
}
}
for example I changed line that have * to this:
dt.Rows[row.DataItemIndex]["subject"] = "tx";
and after edit "subject" column changed to "tx", so I don't know why ((TextBox)(row.Cells[4].Controls[0])).Text return TextBox's text before edit?
Because you're calling DataBind(); method each time page refreshed (POST or GET), let me explain more if user put the new value in the TextBox and click on update button to trigger res_RowUpdating even Page_Load will fire and bind the Gird with database values which is the old values and neglect the user input value.
I think, you just need to rebind the grid
Remove the else part in your page_load.
Should do it for you.
You are binding the Grid every time there is a postback which is not required.
Maybe changes are done but the form is not being updated.
Try putting gridview control inside an Update Panel Control and call UpdatePanel.Update().
When you work with a web control, what you see can be different from what actually is because changes in data are not autoupdated in the presentation layer.
To solve this "problem" you can make a postback (retrieving everything) of the whole page, but this is like killing a fly with a bazooka because you do not need everything, just what has been updated, so for this purpose there are several tool that allow you to make partial updates, for example the AJAX control: UpdatePanel.
Hope it helps.
Update: Call the AcceptChanges() method on the DataTable and erase the else branch on the Page_Load after if(!PostBack)
Call the AcceptChanges() method of the DataTable and then bind the GridView.
I'm new to ASP.NET.
Im developing ASP.NET C# web form which creating GridView components dynamically and filling them using the data received from my webservice.
I'm creating these GridView components programmatically in server-side (cs file)- it has to be flexible - 1 GridView and sometimes 10 GridView components.
The problem occurs when I'm trying to add pagination - whenever the user clicks the "next" page, the whole page is getting refreshed because of a postBack and I'm loosing all my data and the page returns Blank/Empty.
I used PlaceHolder to hold the GridView components, while searching for a solution, I found UpdatePanel as a better alternative - as far as I understand the page can be partially refreshed - which means that only the UpdatePanel has to be refreshed...but it doesn't work.
The following code sample is my TEST, the UpdatePanel is the only component initiated in the client side (.aspx page), the rest initiated programmatically in .cs .
how can I solve the issue described above?
Why does the whole page is getting refreshed and I'm loosing my data?
can you recommend another way? can provide me with any code sample?
If I'm not rebuilding the GridView, it doesn't work...
Here is my Default.aspx.cs
public partial class TestAjaxForm : System.Web.UI.Page
{
DataTable table;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
bindGridView();
}
public void bindGridView()
{
GridView gridView1 = new GridView();
gridView1.AutoGenerateColumns = true;
gridView1.PageSize = 2;
gridView1.AllowPaging = true;
gridView1.PagerSettings.Mode = PagerButtons.Numeric;
gridView1.PagerSettings.Position = PagerPosition.Bottom;
gridView1.PagerSettings.PageButtonCount = 10;
gridView1.PageIndexChanging += new GridViewPageEventHandler(this.GridView1_PageIndexChanging);
table = new DataTable();
table.Columns.Add("FirstName");
table.Columns.Add("LastName");
DataRow row = table.NewRow();
row["FirstName"] = "John";
row["LastName"] = "Johnoson";
table.Rows.Add(row);
row = table.NewRow();
row["FirstName"] = "Johnny";
row["LastName"] = "Marley";
table.Rows.Add(row);
row = table.NewRow();
row["FirstName"] = "Kate";
row["LastName"] = "Li";
table.Rows.Add(row);
panel.ContentTemplateContainer.Controls.Add(gridView1);
gridView1.DataSource = table;
gridView1.DataBind();
}
protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView gridView1 = (GridView)sender;
gridView1.PageIndex = e.NewPageIndex;
gridView1.DataSource = table;
gridView1.DataBind();
}
}
Thank you.
If you want a custom GridView approach to work, you have to recreate and rebind the grid on every page load... that's the problem with dynamic Grids... Dynamic controls don't retain their viewstate, but if you added the grid and dynamically generated the columns, that would work easier for you (because I think it may dynamically remember the columns, or you can set AutoGenerateColumns to true, and it brings in your data row column names).
HTH
You should create your GridView and add it to the control tree in the PreInit or Init event handler so that they have a chance to properly bind to ViewState, and it should be done whether or not there's a postback: if you don't add them in a postback, they obviously won't be there to display anything.
DataBinding can happen later in the page life cycle.
Paging only seems to work if you also use an ObjectDataSource; I've never been able to get it to work with a GridView by itself.
I think the easiest thing to do is have the gridview declared in the aspx page inside the place holder, while the place holder is also contained inside the update panel.
For what I can see, John is not doing anything that can't be declared in the markup itself so that shouldn't be a problem. If for some reason the gridview should not be displayed on the screen, it suffices to set the Visible property of the placeholder to false.
As far as paging is concerned, as RickNz correctly points out, it will only retain the state if you bind the gridview to either a LinqDatasource, SqlDatasource or ObjectDatasource but if you bind it to custom business objects, what you need to do is save the data in Session and rebind it again on PageIndexChanged.
In pseudo code, would be sometging like this.
Page_load
{
If (!IsPostBack)
Binddata();
}
private void Binddata()
{
var data = Getdata();
Gridview1.DataSource= data;
Gridview.DataBind();
Session["data"]=data; // cache the data
}
protected void Gridview1_indexchanged(object sender, GridviewPageEventArgs e)
{
var data= Session["data"];
Gridview1. DataSource=data;
Gridview1.DataBind();
GridView1.PageIndex=e.NewPageIndex;
}
I have a DataTable which is populated from a CSV file then, using a DataGridView the data is edited in memory. As far as I understand the programmatic editing of the data should be done on the DataTable where the user editing is done via. the DataGridView.
However when I add columns programmatically to the DataTable, it is not reflected automatically in the DataGridView and I suspect the converse is also true.
How do you keep the two concurrent? I thought the idea of data binding was that this was automatic...
Also adding rows works fine.
SOLVED:
The AutoGeneratedColumns was set to false in the designer code despite being true in the properties dialog (and set explicitly in the code). The initial columns were generated programmatically and so should not have appeared however this was not picked up on since the designer code also continued to generate 'designed in' columns that were originally used for debugging.
Moral: Check the autogenerated code!
In addition to this, see this post and this post
This doesn't sound right. To test it out, I wrote a simple app, that creates a DataTable and adds some data to it.
On the button1.Click it binds the table to the DataGridView.
Then, I added a second button, which when clicked, adds another column to the underlying DataTable.
When I tested it, and I clicked the second button, the grid immedialtey reflected the update.
To test the reverse, I added a third button which pops up a dialog with a DataGridView that gets bound to the same DataTable. At runtime, I then added some values to the first DataGridView, and when I clicked the button to bring up the dialog, the changes were reflected.
My point is, they are supposed to stay concurrent. Mark may be right when he suggested you check if AutoGenerateColumns is set to true. You don't need to call DataBind though, that's only for a DataGridView on the web. Maybe you can post of what you're doing, because this SHOULD work.
How I tested it:
DataTable table = new DataTable();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
table.Columns.Add("Name");
table.Columns.Add("Age", typeof(int));
table.Rows.Add("Alex", 26);
table.Rows.Add("Jim", 36);
table.Rows.Add("Bob", 34);
table.Rows.Add("Mike", 47);
table.Rows.Add("Joe", 61);
this.dataGridView1.DataSource = table;
}
private void button2_Click(object sender, EventArgs e)
{
table.Columns.Add("Height", typeof(int));
foreach (DataRow row in table.Rows)
{
row["Height"] = 100;
}
}
private void button3_Click(object sender, EventArgs e)
{
GridViewer g = new GridViewer { DataSource = table };
g.ShowDialog();
}
public partial class GridViewer : Form //just has a DataGridView on it
{
public GridViewer()
{
InitializeComponent();
}
public object DataSource
{
get { return this.dataGridView1.DataSource; }
set { this.dataGridView1.DataSource = value; }
}
}
Is AutoGenerateColumns set to true? If you are making changes after the initial Binding you'll also have to call DataBind() to rebind the changed datasource. I know this is true for an AJAX callback, I think it is true for a WinForms control PostBack.
Here is another solution which you dont need to assign a "name" to the data grid, so that the data grid can be a template element.
(In my case, data grid is a template element inside TabControl.ContentTemplate)
The key to show the new column (added programmatically after the initial binding) is forcing the datagrid to refresh.
From the answer in Force WPF DataGrid to regenerate itself, Andres suggested setting AutoGenerateColumns from false to true will force datagrid to refresh.
Which means I simply need to:
Bind the AutoGenerateColumns to a property of my object
Set the propery to false before adding column
Set the propery to true after added column.
Here is the code:
XAML:
<DataGrid AutoGenerateColumns="{Binding toggleToRefresh}"
ItemsSource="{Binding dataTable}"
/>
C#:
public class MyTabItem : ObservableObject
{
private DataTable _dataTable = new DataTable();
public DataTable dataTable
{
get { return _dataTable; }
}
private bool _toggleToRefresh = true;
public bool toggleToRefresh
{
get { return _toggleToRefresh; }
set
{
if (_toggleToRefresh != value)
{
_toggleToRefresh = value;
RaisePropertyChanged("toggleToRefresh");
}
}
}
public void addDTColumn()
{
toggleToRefresh = false;
string newColumnName = "x" + dataTable.Columns.Count.ToString();
dataTable.Columns.Add(newColumnName, typeof(double));
foreach (DataRow row in dataTable.Rows)
{
row[newColumnName] = 0.0;
}
toggleToRefresh = true;
}
public void addDTRow()
{
var row = dataTable.NewRow();
foreach (DataColumn col in dataTable.Columns)
{
row[col.ColumnName] = 0.0;
}
dataTable.Rows.Add(row);
}
}
Hope this help :)
I had the same issue and I issued a DataBind(). It's not the silver bullet for everything, but it's what helped me in a few cases. I had to put it in before capturing information through a DataView, after the EditCommand and UpdateCommand events immediately after the EditItemIndex statement,
protected void datalistUWSolutions_EditCommand(object source, DataListCommandEventArgs e)
{
datalistUWSolutions.EditItemIndex = e.Item.ItemIndex;
datalistUWSolutions.DataBind(); // refresh the grid.
}
and
protected void datalistUWSolutions_UpdateCommand(object source, DataListCommandEventArgs e)
{
objDSSolutions.UpdateParameters["Name"].DefaultValue = ((Label)e.Item.FindControl("lblSolutionName")).Text;
objDSSolutions.UpdateParameters["PriorityOrder"].DefaultValue = ((Label)e.Item.FindControl("lblOrder")).Text;
objDSSolutions.UpdateParameters["Value"].DefaultValue = ((TextBox)e.Item.FindControl("txtSolutionValue")).Text;
objDSSolutions.Update();
datalistUWSolutions.EditItemIndex = -1; // Release the edited record
datalistUWSolutions.DataBind(); // Redind the records for refesh the control
}