Gridview find control in dynamic header row - c#

This may have to do with the page life cycle but just can't seem to get it working, even after finding every post out there on the subject.
In a gridview, a new header row is created with a control:
protected void gvNotes_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
GridView HeaderGrid = (GridView)sender;
GridViewRow HeaderGridRow = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);
TableCell HeaderCell = new TableCell();
CheckBox chk = new CheckBox();
chk.Text = "Show Admin Columns";
chk.ID = "chk";
chk.AutoPostBack = true;
chk.CheckedChanged += new EventHandler(this.chkShowAminColumns_CheckedChanged);
HeaderCell.Controls.Add(chk);
HeaderCell.ColumnSpan = gvNotes.Columns.Count;
HeaderGridRow.Cells.Add(HeaderCell);
gvNotes.Controls[0].Controls.AddAt(0, HeaderGridRow);
}
}
Trying to find this new control is giving me a little trouble:
public void bindNotesGrid()
{
DataTable dt = BLL.NotesBLL.GetNotes();
gvNotes.DataSource = dt;
gvNotes.DataBind();
if (dt.Rows.Count > 0)
{
//never finds the control
foreach (Control c in gvNotes.HeaderRow.Controls)
{
if (c is CheckBox)
{
string value = ((CheckBox)c).Text;
}
}
//never finds the control
//int current = 0;
//int headerCount = gvNotes.HeaderRow.Cells.Count;
//for (current = 0; current < headerCount; current++)
//{
// CheckBox chk2 = (CheckBox)gvNotes.HeaderRow.Cells[current].FindControl("chk");
//}
//returns null
CheckBox chk = (CheckBox)gvNotes.HeaderRow.FindControl("chk");
}
}
All the findcontrol attempts return the checkbox as null.
What am I not seeing here?
Thanks!

The header row is generated by the GridView control based on your data source. It is not actually a member of your dataset but is dynamically built based on the contents of the data set.
Consider this code:
int HeaderRowCount = -5; // initialized to a wrong starting point
protected void GridView1_DataBinding( object sender, EventArgs e ) {
HeaderRowCount = 0; // this event starts the binding and row creation process
}
// Each row is created and Bound in the order of the dataset.
protected void GridView1_RowCreated( object sender, GridViewRowEventArgs e ) {
// Are we creating the Header Row?
if ( e.Row.RowType == DataControlRowType.Header ) {
// Create your additional Headers here: AddHeaderRow() is defined below
AddHeaderRow( ( GridView ) sender, "Hi I'm a header" );
}
}
protected void GridView1_RowDataBound( object sender, GridViewRowEventArgs e ) {
if ( e.Row.RowType == DataControlRowType.Header ) {
HeaderRowCount++;
}
}
protected void GridView1_DataBound( object sender, EventArgs e ) {
GridView1.Caption = string.Format( "HeaderRowCount: {0}", HeaderRowCount);
}
After binding is complete you will see this in the GridView Caption:
HeaderRowCount: 1
The header row count will always be 1 because additional header rows are not part of the binding process. The GridView Rows collection only contain Rows that are part of the DataSet. GridViews generate the HeaderRow (and FooterRow) dynamically.
Any additional Header Rows are only available through the inner Table collection of rows, so you need to search each Table Row for RowType == Header:
Table InnerTable = ( Table ) GridView1.Controls[ 0 ];
foreach ( GridViewRow r in InnerTable.Rows ) {
if (r.RowType == DataControlRowType.Header){
CheckBox chk = (CheckBox) r.FindControl( "chk" );
}
}
Or you can access the rows directly if you wish:
GridViewRow r = ( GridViewRow ) InnerTable.Rows[0];
CheckBox chk = (CheckBox) r.FindControl( "chk" );
AddHeaderRow()
private void AddHeaderRow( GridView gv, string HeaderText ) {
Table InnerTable = ( Table ) gv.Controls[ 0 ];
GridViewRow row = new GridViewRow( 0, -1, DataControlRowType.Header, DataControlRowState.Normal );
TableCell th = new TableHeaderCell();
th.HorizontalAlign = HorizontalAlign.Center;
th.ColumnSpan = gv.Columns.Count;
th.Font.Bold = true;
th.Text = HeaderText;
row.Cells.Add( th );
InnerTable.Rows.AddAt( 0, row );
}

To find the control try this:-
foreach (Control c in gvNotes.Controls[0].Controls[0].Controls)
{
CheckBox chk = (CheckBox)c.FindControl("chk");
}
gvNotes.Controls[0].Controls -> System.Web.UI.WebControls.Table.RowControlCollection
gvNotes.Controls[0].Controls[0].Controls -> System.Web.UI.WebControls.TableRow.CellControlCollection
as first you added TableRow and then TableCell
Hop this will help

Related

Not Changeable Row number column in datagridview

I want to extend a dategridview with a (read only) column just for row number.
The ROW NUMBER row`s order should not change when datagridview sort by other column content (Like excel)!
is possible?
We can enumerate each row in one of two ways:
Adding a new column.
Within the row header.
Displaying in Added Column
private void AddIndexCol()
{
DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn();
col.Name = "Index";
col.HeaderText = "Index";
col.ReadOnly = true;
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
cell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
col.CellTemplate = cell;
this.dataGridView1.Columns.Insert(0, col);
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex == 0)
{
e.Value = String.Format("{0}", e.RowIndex + 1);
e.FormattingApplied = true;
}
}
Credit to ASh for the CellFormatting code.
Displaying in RowHeader
public Form1()
{
InitializeComponent();
DataGridViewCellStyle style = new DataGridViewCellStyle();
style.Alignment = DataGridViewContentAlignment.MiddleCenter;
this.dataGridView1.RowHeadersDefaultCellStyle = style;
this.dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders;
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewRowHeaderCell header = this.dataGridView1.Rows[e.RowIndex].HeaderCell;
if (e.ColumnIndex == 0) // (header.Value == null)
{
header.Value = String.Format("{0}", e.RowIndex + 1);
}
}
Note about the if statement. The condition e.ColumnIndex == 0 will always preserve numeric order through sorting while the condition header.Value == null will preserve row numbers with the original row (but will need additional code when handling row deletion). For example, this descending sort:
Col == 0 Header == null
1 a => 1 c 1 a => 3 c
2 b 2 b 2 b 2 b
3 c 3 a 3 c 1 a

I have added dropdownlist at first row of gridview.Now i want to bind this dropdownlist with some static column

Dropdownlist at first row is empty.i need to add column inside dropdown.here is my code:
private void grdbind()
{
DataTable db = new DataTable();
db = (DataTable)Session["csvdata"];
DataRow newrow = db.NewRow();
db.Rows.InsertAt(newrow, 0);
dgData.DataSource = db;
dgData.DataBind();
}
And this code is use to add dropdown at first position:
protected void dgData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl;
if (e.Row.RowIndex == 0)
{
for (Int32 i = 0; i < e.Row.Cells.Count; i++)
{
ddl = new DropDownList();
ddl.ID = "ddlCol" + i.ToString();
e.Row.Cells[i].Controls.Add(ddl);
}
}
}
Now what i want is to bind this dropdown.??

Getting dynamic control values inside a dynamically created table

I am trying to read my checkbox values in my table cells, however while doing a postback via button submit, the entire table disappears. I only create the table if it's not a postback when a page_load occurs and I thought the table would persist across postback once created.
How do I retain the entire table with its cell's checkboxes values? Thanks.
protected void CreateTable()
{
int rowCnt; // Total number of rows.
int rowCtr; // Current row count.
int cellCtr; // Total number of cells per row (columns).
int cellCnt; // Current cell counter.
rowCnt = 6;
cellCnt = 8;
string baseStartTime = (ConfigurationManager.AppSettings["DEFAULTBASESELLSCHEDULETIME"]);
int incrementInMins = Convert.ToInt32((ConfigurationManager.AppSettings["DEFAULTBASESELLSCHEDULETIME_INCREMENT"]));
DateTime tempTimeFrom = Convert.ToDateTime(baseStartTime); // Converts only the time
tempTimeFrom = tempTimeFrom.AddMinutes(-incrementInMins);
// Because the very first loop will add 30 mins right away
for (rowCtr = 1; rowCtr <= rowCnt; rowCtr++)
{
tempTimeFrom = tempTimeFrom.AddMinutes(incrementInMins);
DateTime tempTimeTo = tempTimeFrom.AddMinutes(incrementInMins);
string timeFrom = tempTimeFrom.ToString("hh:mm tt");
string timeToClassName = tempTimeTo.ToString("hh:mm");
string timeTo = tempTimeTo.ToString("hh:mm tt");
// Create a new row and add it to the table.
TableRow tRow = new TableRow();
tblSellSchedule.Rows.Add(tRow);
for (cellCtr = 1; cellCtr <= cellCnt; cellCtr++)
{
// Create a new cell and add it to the row.
TableCell tCell = new TableCell();
tRow.Cells.Add(tCell);
if (cellCtr == 1) // We need the time for the first column of every row
{
tCell.Controls.Add(new LiteralControl(timeFrom + "-" + timeTo));
tCell.CssClass = timeToClassName;
}
else
{
// tCell.Controls.Add(new LiteralControl("Select"));
CheckBox chkbox = new CheckBox();
chkbox.ID = tblSellSchedule.Rows[rowCtr - 1].Cells[0].CssClass + (cellCtr - 1);
tCell.Controls.Add(chkbox);
// tCell.ID = (cellCtr - 1).ToString();
tCell.CssClass = (cellCtr - 1).ToString();
}
}
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
foreach (TableRow row in tblSellSchedule.Rows)
{
foreach (TableCell cell in row.Cells)
{
foreach (CheckBox c in cell.Controls.OfType<CheckBox>())
{
if (c.Checked)
{
var idVal = c.ID;
}
}
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
CreateTable();
}
}
I think you should call your method CreateTable() in page_Init().
because on every post back every DOM content you have created will be vanished. so you have to create it again on every post back, so you have to do this recreation in page_Init() that is accessed before page_Load().

Check All Checkbox items on DataGridView

Here's the scenario.
I have checkbox(Name:"Check All" ID:chkItems) and datagridview. And when I click on this checkbox, all checkboxes on the datagridview will also be checked.
I've also added the checkbox column on the grid.
DataGridViewCheckBoxColumn CheckboxColumn = new DataGridViewCheckBoxColumn();
CheckBox chk = new CheckBox();
CheckboxColumn.Width = 20;
GridView1.Columns.Add(CheckboxColumn);
Here is the code behind of the checkbox. There is a problem on the row.Cell
private void chkItems_CheckedChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow row in GridView1.Rows)
{
DataGridViewCheckBoxCell chk = e.row.Cells(0);
if (chk.Selected == false)
{
row.Cells(0).Value = true;
}
}
}
DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell) row.Cells[0];
instead of
DataGridViewCheckBoxCell chk = e.row.Cell(0);
*EDIT:*I think you really want to do this:
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell) row.Cells[0];
chk.Value = !(chk.Value == null ? false : (bool) chk.Value); //because chk.Value is initialy null
}
private void setCheckBoxInDataGrid(DataGridView dgv, int pos, bool isChecked)
{
for (int i = 0; i < dgv.RowCount; i++)
{
dgv.Rows[i].DataGridView[pos, i].Value = isChecked;
}
}
This is how I did it
Try this one
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
row.Cells[0].Value = row.Cells[0].Value == false ? true : false;
}
If you are okay with providing a default state to the checkboxes of datagridview on your own i.e either True or False[Do not assign a null state] state(Reason for doing this would be explained in the latter).
Which could be done by the following code,(type in this code when you search for results to be viewed in DataGridView)
dgv is the object of the DataGridView that you are using.
for (int i = 0; i < dgv.RowCount - 1; i++)
{
dgv.Rows[i].DataGridView[0, i].Value = true;
}
Where DataGridView[0, i] indicates 0th column ith row
The Reason for doing this is,On load the checkbox is by default in a null state. The code isn't comparing for null state(Creating a object null reference exception). So, once when u assign it a state either a false or true . It can never undergo into null state.
Type in the following code inside the button_click_event using which you are going to check
for (int i = 0; i < dgv.RowCount-1; i++)
{
if (dgv.Rows[i].Cells[0].Value.ToString() != "")
{
dgv.Rows[i].Cells[0].Value = false;
}
else
{
dgv.Rows[i].Cells[0].Value = true;
}
}
It Worked for me, I hope it does for you.
I tried to select all checkbox or select it mutuality and calculate some value...so wrote this code that's maybe helpful.
foreach (DataGridViewRow item in DGDoc.Rows)
{
if (item.Cells[0].Value == null)
item.Cells[0].Value = "True";
if (bool.Parse(item.Cells[0].Value.ToString()))
{
item.DefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(241, 215, 215);
strIDs += "," + item.Cells[1].Value.ToString();
intSumPrice += Int64.Parse(item.Cells[4].Value.ToString());
intSumTax += Int64.Parse(item.Cells[5].Value.ToString());
intSumPay += Int64.Parse(item.Cells[6].Value.ToString());
}
else
{
item.DefaultCellStyle.BackColor = System.Drawing.Color.Empty;
}
}
DGDoc.EndEdit();
1- Create new button.
2- You can use the following code when click checkAll button
3- when click the button it will check all checkboxes in datagridview and when click again it will uncheck all boxes.
private void btncheckall_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dgvResult.Rows)
{
row.Cells[0].Value = row.Cells[0].Value == null ? false : !(bool)row.Cells[0].Value;
}
}
Note: in some cases you have to click in datagridview first then click the button.
You can check all cells like this:
private void CheckAllCheckboxItemsOnDataGridView(int columnIndex)
{
foreach (DataGridViewRow row in dgFiles.Rows)
{
DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)row.Cells[columnIndex];
cell.Value = !(cell.Value == null ? false : (bool)cell.Value);
}
}
You can use method in CheckedChanged event like this:
private void chkItems_CheckedChanged(object sender, EventArgs e)
{
CheckAllCheckboxItemsOnDataGridView(columnIndex: 0);
}
This is my version, which allows a more natural behavior I'd say; if one of the checkboxes is ticked, all checkboxes are ticked as well when selecting all.
How it'll be usefull to you :)
private void BtnSelectAll_Click(object sender, EventArgs e)
{
List<Boolean> chkList = new List<Boolean>();
bool ticked = false;
foreach (DataGridViewRow row in dataGrid.Rows)
{
DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell)row.Cells[0];
chkList.Add((bool)chk.Value);
}
if (!chkList.Contains(true))
{
ticked = true;
}
else if (!chkList.Contains(false))
{
ticked = false;
} else
{
ticked = true;
}
foreach (DataGridViewRow row in dataGrid.Rows)
{
DataGridViewCheckBoxCell chk = (DataGridViewCheckBoxCell)row.Cells[0];
chk.Value = ticked;
}
}

DataGridView Selected Row Move UP and DOWN

How can I allow selected rows in a DataGridView (DGV) to be moved up or down. I have done this before with a ListView. Unfortunetly, for me, replacing the DGV is not an option (curses). By the way, the DGV datasource is a Generic Collection.
The DGV has two buttons on the side, yes, UP & Down. Can anyone help point me in the right direction. I do have the code that I used for the ListView if it'll help (it did not help me).
Just to expand on Yoopergeek's answer, here's what I have.
I was not using a DataSource (data is being dropped to registry on form close, and reload on form load)
This sample will keep rows from being moved off the grid and lost, and reselect the cell the person was in as well.
To make things simpler for copy / paste, I modified so you need only change "gridTasks" to your DataGridView's name, rather than renaming it throughout the code.
This solution works only for single cell/row selected.
private void btnUp_Click(object sender, EventArgs e)
{
DataGridView dgv = gridTasks;
try
{
int totalRows = dgv.Rows.Count;
// get index of the row for the selected cell
int rowIndex = dgv.SelectedCells[ 0 ].OwningRow.Index;
if ( rowIndex == 0 )
return;
// get index of the column for the selected cell
int colIndex = dgv.SelectedCells[ 0 ].OwningColumn.Index;
DataGridViewRow selectedRow = dgv.Rows[ rowIndex ];
dgv.Rows.Remove( selectedRow );
dgv.Rows.Insert( rowIndex - 1, selectedRow );
dgv.ClearSelection();
dgv.Rows[ rowIndex - 1 ].Cells[ colIndex ].Selected = true;
}
catch { }
}
private void btnDown_Click(object sender, EventArgs e)
{
DataGridView dgv = gridTasks;
try
{
int totalRows = dgv.Rows.Count;
// get index of the row for the selected cell
int rowIndex = dgv.SelectedCells[ 0 ].OwningRow.Index;
if ( rowIndex == totalRows - 1 )
return;
// get index of the column for the selected cell
int colIndex = dgv.SelectedCells[ 0 ].OwningColumn.Index;
DataGridViewRow selectedRow = dgv.Rows[ rowIndex ];
dgv.Rows.Remove( selectedRow );
dgv.Rows.Insert( rowIndex + 1, selectedRow );
dgv.ClearSelection();
dgv.Rows[ rowIndex + 1 ].Cells[ colIndex ].Selected = true;
}
catch { }
}
This should work. I use a BindingSource instead of binding my List directly to the DataGridView:
private List<MyItem> items = new List<MyItem> {
new MyItem {Id = 0, Name = "Hello"},
new MyItem {Id = 1, Name = "World"},
new MyItem {Id = 2, Name = "Foo"},
new MyItem {Id = 3, Name = "Bar"},
new MyItem {Id = 4, Name = "Scott"},
new MyItem {Id = 5, Name = "Tiger"},
};
private BindingSource bs;
private void Form1_Load(object sender, EventArgs e)
{
bs = new BindingSource(items, string.Empty);
dataGridView1.DataSource = bs;
}
private void button1_Click(object sender, EventArgs e)
{
if (bs.Count <= 1) return; // one or zero elements
int position = bs.Position;
if (position <= 0) return; // already at top
bs.RaiseListChangedEvents = false;
MyItem current = (MyItem)bs.Current;
bs.Remove(current);
position--;
bs.Insert(position, current);
bs.Position = position;
bs.RaiseListChangedEvents = true;
bs.ResetBindings(false);
}
private void button2_Click(object sender, EventArgs e)
{
if (bs.Count <= 1) return; // one or zero elements
int position = bs.Position;
if (position == bs.Count - 1) return; // already at bottom
bs.RaiseListChangedEvents = false;
MyItem current = (MyItem)bs.Current;
bs.Remove(current);
position++;
bs.Insert(position, current);
bs.Position = position;
bs.RaiseListChangedEvents = true;
bs.ResetBindings(false);
}
public class MyItem
{
public int Id { get; set; }
public String Name { get; set; }
}
If you programatically change the ordering of the items in your collection, the DGV should reflect that automatically.
Sloppy, half-working example:
List<MyObj> foo = DGV.DataSource;
int idx = DGV.SelectedRows[0].Index;
int value = foo[idx];
foo.Remove(value);
foo.InsertAt(idx+1, value)
Some of that logic may be wrong, and this may not be the most efficient approach either. Also, it doesn't take into account multiple row selections.
Hmm, one last thing, if you're using a standard List or Collection this isn't going to go as smoothly. List and Collection on't emit events that the DGV finds useful for databinding. You could 'burp' the databinding every time you change the collection, but a better solution would be for you to use a System.ComponentModel.BindingList. When you change the ordering of the BindingList the DGV should reflect the change automatically.
There is a much simpler way that most posts here (in my opinion). Performing the action for an "up" button click is basically just a swap of rows with the one above. If you are controlling the values yourself (as the question was stated) then you just need to swap the values of the rows. Quick and simple!
NOTE: this works only when multiselect is disabled on the datagrid! As you can tell I am only paying attention to item at index 0 in the SelectedRows collection.
Here is what I used:
private void btnUp_Click(object sender, EventArgs e)
{
var row = dgvExportLocations.SelectedRows[0];
if (row != null && row.Index > 0)
{
var swapRow = dgvExportLocations.Rows[row.Index - 1];
object[] values = new object[swapRow.Cells.Count];
foreach (DataGridViewCell cell in swapRow.Cells)
{
values[cell.ColumnIndex] = cell.Value;
cell.Value = row.Cells[cell.ColumnIndex].Value;
}
foreach (DataGridViewCell cell in row.Cells)
cell.Value = values[cell.ColumnIndex];
dgvExportLocations.Rows[row.Index - 1].Selected = true;//have the selection follow the moving cell
}
}
To perform a "down" click you can do the opposite as well, same logic
First fill your datagridview,for example you got table with 3 colums
DataTable table = new DataTable();
table.Columns.Add("col1");
table.Columns.Add("col2");
table.Columns.Add("col3");
foreach (var i in yourTablesource(db,list,etc))
{
table.Rows.Add(i.col1, i.col2, i.col2);
}
datagridview1.DataSource = table;
Then, on button up click
int rowIndex;
private void btnUp_Click(object sender, EventArgs e)
{
rowIndex = datagridview1.SelectedCells[0].OwningRow.Index;
DataRow row = table.NewRow();
row[0] = datagridview1.Rows[rowIndex].Cells[0].Value.ToString();
row[1] = datagridview1.Rows[rowIndex].Cells[1].Value.ToString();
row[2] = datagridview1.Rows[rowIndex].Cells[2].Value.ToString();
if (rowIndex > 0)
{
table.Rows.RemoveAt(rowIndex);
table.Rows.InsertAt(row, rowIndex - 1);
datagridview1.ClearSelection();
datagridview1.Rows[rowIndex - 1].Selected = true;
}
}
Do the same thing for button down, just change row index from rowIndex - 1 to rowindex + 1 in your buttonDown_Click method
Was looking for this UP/DOWN button thing and glad that I found this.
Better to put the bs.RaiseListChangedEvents = false statement after the return or it doesn't work all the time.
And in C#3.0 you can add two extension methods to the BindingSource like this:
public static class BindingSourceExtension
{
public static void MoveUp( this BindingSource aBindingSource )
{
int position = aBindingSource.Position;
if (position == 0) return; // already at top
aBindingSource.RaiseListChangedEvents = false;
object current = aBindingSource.Current;
aBindingSource.Remove(current);
position--;
aBindingSource.Insert(position, current);
aBindingSource.Position = position;
aBindingSource.RaiseListChangedEvents = true;
aBindingSource.ResetBindings(false);
}
public static void MoveDown( this BindingSource aBindingSource )
{
int position = aBindingSource.Position;
if (position == aBindingSource.Count - 1) return; // already at bottom
aBindingSource.RaiseListChangedEvents = false;
object current = aBindingSource.Current;
aBindingSource.Remove(current);
position++;
aBindingSource.Insert(position, current);
aBindingSource.Position = position;
aBindingSource.RaiseListChangedEvents = true;
aBindingSource.ResetBindings(false);
}
}
Finally a good use for extension methods instead of all those bad String examples.. ;-)
DataGridViewRow BeginingRow = new DataGridViewRow();
int BeginingRowIndex ;
private void DataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button != MouseButtons.Left ||e.RowIndex < 0 ) return;
if (BeginingRowIndex > e.RowIndex)
{
DataGridView1.Rows.Insert(e.RowIndex);
foreach (DataGridViewCell cellules in BeginingRow.Cells)
{
DataGridView1.Rows[e.RowIndex].Cells[cellules.ColumnIndex].Value = cellules.Value;
}
DataGridView1.Rows.RemoveAt(BeginingRowIndex + 1);
}
else
{
DataGridView1.Rows.Insert(e.RowIndex +1);
foreach (DataGridViewCell cellules in BeginingRow.Cells)
{
DataGridView1.Rows[e.RowIndex+1].Cells[cellules.ColumnIndex].Value = cellules.Value;
}
DataGridView1.Rows.RemoveAt(BeginingRowIndex);
}
DataGridView1.RowsDefaultCellStyle.ApplyStyle(BeginingRow.DefaultCellStyle);
DataGridView1.Rows[e.RowIndex].Selected = true;
}
private void DataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.Button != MouseButtons.Left ||e.RowIndex < 0 ) return;
BeginingRowIndex = e.RowIndex;
BeginingRow = DataGridView1.Rows[BeginingRowIndex];
BeginingRow.DefaultCellStyle = DataGridView1.Rows[BeginingRowIndex].DefaultCellStyle;
}
private void butUp_Click(object sender, EventArgs e)
{
DataTable dtTemp = gridView.DataSource as DataTable;
object[] arr = dtTemp.Rows[0].ItemArray;
for (int i = 1; i < dtTemp.Rows.Count; i++)
{
dtTemp.Rows[i - 1].ItemArray = dtTemp.Rows[i].ItemArray;
}
dtTemp.Rows[dtTemp.Rows.Count - 1].ItemArray = arr;
}
private void butDown_Click(object sender, EventArgs e)
{
DataTable dtTemp = gridView.DataSource as DataTable;
object[] arr = dtTemp.Rows[dtTemp.Rows.Count - 1].ItemArray;
for (int i = dtTemp.Rows.Count - 2; i >= 0; i--)
{
dtTemp.Rows[i + 1].ItemArray = dtTemp.Rows[i].ItemArray;
}
dtTemp.Rows[0].ItemArray = arr;
}
this is the shortest solution I have found to the problem and I just refactored a little bit the code found in:
http://dotnetspeaks.net/post/Moving-GridView-Rows-Up-Down-in-a-GridView-Control.aspx
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" Font-Names="Verdana" Font-Size="9pt" runat="server" OnRowCreated="GridView1_RowCreated"
AutoGenerateColumns="False" CellPadding="4" BorderColor="#507CD1" BorderStyle="Solid">
<Columns>
<asp:TemplateField HeaderText="First Name">
<ItemTemplate>
<asp:Label ID="txtFirstName" runat="server" Text='<%# Eval("FirstName") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
<asp:Button ID="btnUp" runat="server" Text="Up" OnClick="btnUp_Click"/>
<asp:Button ID="btnDown" runat="server" Text="Down" OnClick="btnDown_Click" />
</form>
and with code behind...
public int SelectedRowIndex { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Test Records
GridView1.DataSource = Enumerable.Range(1, 5).Select(a => new
{
FirstName = String.Format("First Name {0}", a),
LastName = String.Format("Last Name {0}", a),
});
GridView1.DataBind();
}
}
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Attributes["onmouseover"] = "this.style.cursor='pointer'";
e.Row.ToolTip = "Click to select row";
e.Row.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(GridView1, "Select$" + e.Row.RowIndex);
}
}
protected void btnUp_Click(object sender, EventArgs e)
{
var rows = GridView1.Rows.Cast<GridViewRow>().Where(a => a != GridView1.SelectedRow).ToList();
//If First Item, insert at end (rotating positions)
if (GridView1.SelectedRow.RowIndex.Equals(0))
{
rows.Add(GridView1.SelectedRow);
SelectedRowIndex = GridView1.Rows.Count -1;
}
else
{
SelectedRowIndex = GridView1.SelectedRow.RowIndex - 1;
rows.Insert(GridView1.SelectedRow.RowIndex - 1, GridView1.SelectedRow);
}
RebindGrid(rows);
}
protected void btnDown_Click(object sender, EventArgs e)
{
var rows = GridView1.Rows.Cast<GridViewRow>().Where(a => a != GridView1.SelectedRow).ToList();
//If Last Item, insert at beginning (rotating positions)
if (GridView1.SelectedRow.RowIndex.Equals(GridView1.Rows.Count - 1))
{
rows.Insert(0, GridView1.SelectedRow);
SelectedRowIndex = 0;
}
else
{
SelectedRowIndex = GridView1.SelectedRow.RowIndex + 1;
rows.Insert(GridView1.SelectedRow.RowIndex + 1, GridView1.SelectedRow);
}
RebindGrid(rows);
}
private void RebindGrid(IEnumerable<GridViewRow> rows)
{
GridView1.DataSource = rows.Select(a => new
{
FirstName = ((Label)a.FindControl("txtFirstName")).Text,
}).ToList();
GridView1.SelectedIndex = SelectedRowIndex;
GridView1.DataBind();
}
Header 3
private void buttonX8_Click(object sender, EventArgs e)//down
{
DataGridViewX grid = dataGridViewX1;
try
{
int totalRows = grid.Rows.Count;
int idx = grid.SelectedCells[0].OwningRow.Index;
if (idx == totalRows - 1 )
return;
int col = grid.SelectedCells[0].OwningColumn.Index;
DataGridViewRowCollection rows = grid.Rows;
DataGridViewRow row = rows[idx];
rows.Remove(row);
rows.Insert(idx + 1, row);
grid.ClearSelection();
grid.Rows[idx + 1].Cells[col].Selected = true;
private void buttonX8_Click(object sender, EventArgs e)//down
{
DataGridViewX grid = dataGridViewX1;
try
{
int totalRows = grid.Rows.Count;
int idx = grid.SelectedCells[0].OwningRow.Index;
if (idx == totalRows - 1 )
return;
int col = grid.SelectedCells[0].OwningColumn.Index;
DataGridViewRowCollection rows = grid.Rows;
DataGridViewRow row = rows[idx];
rows.Remove(row);
rows.Insert(idx + 1, row);
grid.ClearSelection();
grid.Rows[idx + 1].Cells[col].Selected = true;
}
catch { }
}
SchlaWiener's answer worked well, and I just wanna add something to it:
private void button1_Click(object sender, EventArgs e) //The button to move up
{
int position = bs.Position;
//.......neglected.......
dataGridView1.ClearSelection();
dataGridView1.Rows[position].Selected = true;
bs.MovePrevious();
}
Adding those 3 lines at the bottom to also make the selection move (both bindingSource and dataGridView), so that we can continuously click the bottom to move a row up.
For moving down just call bs.MoveNext()
(I have not enough reputation to post as comment yet)
data bound solution with multi-selection support, use SharpDevelop 4.4 to convert to C#.
<Extension()>
Sub MoveSelectionUp(dgv As DataGridView)
If dgv.CurrentCell Is Nothing Then Exit Sub
dgv.CurrentCell.OwningRow.Selected = True
Dim items = DirectCast(dgv.DataSource, BindingSource).List
Dim selectedIndices = dgv.SelectedRows.Cast(Of DataGridViewRow).Select(Function(row) row.Index).Sort
Dim indexAbove = selectedIndices(0) - 1
If indexAbove = -1 Then Exit Sub
Dim itemAbove = items(indexAbove)
items.RemoveAt(indexAbove)
Dim indexLastItem = selectedIndices(selectedIndices.Count - 1)
If indexLastItem = items.Count Then
items.Add(itemAbove)
Else
items.Insert(indexLastItem + 1, itemAbove)
End If
End Sub
<Extension()>
Sub MoveSelectionDown(dgv As DataGridView)
If dgv.CurrentCell Is Nothing Then Exit Sub
dgv.CurrentCell.OwningRow.Selected = True
Dim items = DirectCast(dgv.DataSource, BindingSource).List
Dim selectedIndices = dgv.SelectedRows.Cast(Of DataGridViewRow).Select(Function(row) row.Index).Sort
Dim indexBelow = selectedIndices(selectedIndices.Count - 1) + 1
If indexBelow >= items.Count Then Exit Sub
Dim itemBelow = items(indexBelow)
items.RemoveAt(indexBelow)
Dim indexAbove = selectedIndices(0) - 1
items.Insert(indexAbove + 1, itemBelow)
End Sub
// Down
DataGridViewRow row = new DataGridViewRow();
int index = 0;
row = dgv.SelectedRows[0];
index = dgv.SelectedRows[0].Index;
dgv.Rows.Remove(dgv.SelectedRows[0]);
dgv.Rows.Insert(index + 1, row);
dgv.ClearSelection();
dgv.Rows[index + 1].Selected = true;
// Up
DataGridViewRow row = new DataGridViewRow();
int index = 0;
row = dgv.SelectedRows[0];
index = dgv.SelectedRows[0].Index;
dgv.Rows.Remove(dgv.SelectedRows[0]);
dgv.Rows.Insert(index-1, row);
dgv.ClearSelection();
dgv.Rows[index - 1].Selected = true;
Where dgv is your DataGridView.
Try this:
private void buttonX9_Click(object sender, EventArgs e)//up
{
DataGridViewX grid = dataGridViewX1;
try
{
int totalRows = grid.Rows.Count;
int idx = grid.SelectedCells[0].OwningRow.Index;
if (idx == 0)
return;
int col = grid.SelectedCells[0].OwningColumn.Index;
DataGridViewRowCollection rows = grid.Rows;
DataGridViewRow row = rows[idx];
rows.Remove(row);
rows.Insert(idx - 1, row);
grid.ClearSelection();
grid.Rows[idx - 1].Cells[col].Selected = true;
}
catch { }
}

Categories