all. I'm having a problem getting the GridView.AutoGenerateEditButton property to do anything for me. Right now, I set it to true, and I don't even get the button added to my GridView, so obviously I can't even get any further to code the actual events. Here is what I have so far (sorry for the messy code; I'm getting close to my deadline and it's been a bit frantic):
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
using(SqlDataReader dr = cmd.ExecuteReader())
{
DataSet ds1 = new DataSet();
DataTable dt1 = ds1.Tables.Add("Specs 1");
if (dt1.Rows.Count == 0)
{
ds1.Tables["Specs 1"].Columns.Add("General Information");
ds1.Tables["Specs 1"].Columns.Add("Customer Name");
ds1.Tables["Specs 1"].Columns.Add("Address");
// etc.
}
while (dr.Read())
{
DataRow newRow = ds1.Tables["Specs 1"].NewRow();
int x = 0;
foreach (DataColumn thisColumn in ds1.Tables["Specs 1"].Columns)
{
newRow[ds1.Tables["Specs 1"].Columns[x]] = Convert.ToString(dr[x]);
x += 1;
}
ds1.Tables["Specs 1"].Rows.Add(newRow);
}
DataSet flipped_ds1 = FlipDataSet(ds1); // Flips the dataset's orientation.
Then, when it's time for me to add the GridView to the page, I use the following code:
GridView outputGrid1 = new GridView();
outputGrid1.ShowHeader = false; // Remove the integer headings.
outputGrid1.DataSource = flipped_ds1;
outputGrid1.DataBind();
outputGrid1.AutoGenerateEditButton = true;
Controls.Add(outputGrid1);
Now, the columns are being added exactly the way that I want, and the data is populating properly. However, I don't have the edit buttons that I assume I should have by setting the GridView.AutoGenerateEditButton property to true. I'm sure I'm missing something simple; can someone help? Thanks very much.
Have you tried setting the AutoGenerateEditButton before the call to DataBind() ? Is there a way to prevent updates in your DataSet (the introspection may detect it and avoid providing a useless button maybe) ?
Related
How to program Combox in dataGridView?
The following code does not lead to the result.
Data tables parsitsya in Datatable.
I want to make the "combox" displayed for the "Type" field
Code
DataTable dt;
OleDbConnection connection;
OleDbDataAdapter adapter;
OleDbCommandBuilder commandBuilder;
static string catBD = #"z:\vs\csharp\prb\db_GridVAccess.accdb";
string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}", catBD);
string sql = "SELECT * FROM tbl_01_Combox";
public Form5()
{
InitializeComponent();
using (OleDbConnection cn = new OleDbConnection())
{
connection = new OleDbConnection(connectionString);
connection.Open();
adapter = new OleDbDataAdapter(sql, connection);
commandBuilder = new OleDbCommandBuilder(adapter);
// На соновании DataTable
dt = new DataTable();
adapter.Fill(dt);
dataGridView1.DataSource = dt;
}
}
private void Form5_Load(object sender, EventArgs e)
{
// Ширина поля
dataGridView1.Columns[0].Width = 50;
// Комбокс
string[] countrys = new string[] { "США", "ОАЭ", "ЮАР" };
(dataGridView1.Columns[1] as DataGridViewComboBoxColumn).DataSource = countrys;
}
I believe the problem is your "countrys" isn't observable, plus it has to be a property.
Consider the following code:
private ObservableCollection<string> _Countries;
public ObservableCollection<string> Countries
{
get { return _Countries; }
set { _Countries = value; }
}
Initialize and set its contents in your Form5_Load and see if it works.
EDIT 1:
I was curious, so I actually created a project and tried to recreate the problem, and I believe the real problem here is that your DataGridView is populated according to the info you get from DB. I looked into it a bit further, and found this post on SO:
C# Replace default textbox in DataGridView with a Combobox
According to it, you can't change the type of the column to DataGridViewComboBoxColumn, after it's already been created as DataGridViewTextBoxColumn according to the data you got from DB. It also suggests two different approaches to the case, which do sound realistic. I hope you can figure it out, good luck.
EDIT 2:
Per your request, I'll try to figure the way to accomplish it with changing the data you get from DB.
In the following piece of code, you have a "dt" object which has data that you want to show in your DataGridView.
dt = new DataTable();
adapter.Fill(dt);
dataGridView1.DataSource = dt;
I've never done it myself, and I can't really recreate it anyhow fast, but I suggest you try and play with the contents of the object "dt". I suppose the code which happens in "adapter.Fill" creates the DataTable according to the data from db, you can try and add there some code which will add a List instead of a string for the "type" column (It will then help create a ComboBoxColumn instead of TextBoxColumn as far as I follow). I actually checked it our right now, and it looks to be a bit complicated, but I really don't know what's happening there in your program, it might just be as easy as it gets.
Anyway, I did try to do it another way, instead of changing the existing column type, I added a new DataGridViewComboBoxColumn of my own, to the end of the automatically populated DataGridView:
DataTable dt = new DataTable();
dataGridView2.DataSource = dt;
DataGridViewComboBoxColumn newColumn = new DataGridViewComboBoxColumn();
newColumn.DataSource = new List<string> { "asd", "qwe", "zxc" };
dataGridView2.Columns.Add(newColumn);
You then can just remove/delete the irrelevant "type" column that you got from db. But, then you'll face some other problems along the way, as connecting the selected object in combobox to the other data in the row. It's not complicated, but can get relatively ugly.
Edited:
If you have set the DataGridView.AutoGenerateColumns = true and the columns are generated automatically, the type of column "type" is not ComboBox. in that case you can create a new column, set it up and then replace the old column with it:
DataGridViewComboBoxColumn column = new DataGridViewComboBoxColumn();
int i = 0;
column.DataPropertyName = "type";
column.DataSource = countrys.Select(x => new { Key = i++, Value = x }).ToList();
column.DisplayMember = "Value";
column.ValueMember = "Key";
dataGridView1.Columns.RemoveAt(1);
dataGridView1.Columns.Insert(1, column);
the previous code didn't work because column[1] could not be cast into DataGridViewComboBoxColumn so (dataGridView1.Columns[1] as DataGridViewComboBoxColumn) would return a null and because you have put the code in Form_Load the Exception was omitted.
Original:
try this:
int i = 0;
(dataGridView1.Columns[1] as DataGridViewComboBoxColumn).DataSource = countrys.Select(x=> new {Key = i++, Value = x}).ToList();
(dataGridView1.Columns[1] as DataGridViewComboBoxColumn).DisplayMember = "Value";
(dataGridView1.Columns[1] as DataGridViewComboBoxColumn).ValueMember = "Key";
I have bind DataGridView in C# WinForms from text file as shown below
onPageLoad
DataTable table = new DataTable();
table.Columns.Add(Column0);
table.Columns.Add(Column1);
table.Columns.Add(Column2);
table.Columns.Add(Column3);
using (StreamReader sr = new StreamReader(Environment.CurrentDirectory + #"/data.txt"))
{
while (!sr.EndOfStream)
{
string[] parts = sr.ReadLine().Split(',');
DeviceIDCounter = DeviceIDCounter + 1;
table.Rows.Add(DeviceIDCounter, parts[0], parts[1], parts[2]);
}
}
dataSet = new DataSet();
dataSet.Clear();
dataSet.Tables.Add(table);
dataGridView1.DataSource = dataSet.Tables[0];
dataGridView1.AllowUserToAddRows = false;
dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView1.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
dataGridView1.Columns[3].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
DeviceIDCounter = 0;
Now on updating single row in the dataGridView1, it always return all rows
onButtonClick after updating row
DataTable dtRecordsUpdated = dataSet.Tables[0].GetChanges(); //always returning total rows
if (dtRecordsUpdated != null && dtRecordsUpdated.Rows.Count > 0)
{
Cursor.Current = Cursors.WaitCursor;
Cursor.Current = Cursors.Default;
}
else
{}
On the other hand, my other function which is bind DataGridView from SQLServer is working as expected.
Thanks
You need to update to DataSource of DGV after you made some changes like this:
((System.Data.DataTable)this.dataGridView1.DataSource).AcceptChanges();
DataTable.GetChanges Method: Gets a copy of the DataTable that contains all changes made to it since it was loaded or AcceptChanges was last called.
If you need to catch what has changed you need to AcceptChanges
You get all the rows because the dataTable considers that all the rows have New.State since you never acceptChanges
PS : there is no need to create the DataSet if you are just passing the DataTable to the DataGridView
So i have a form that looks like this:
Image Link
and I generate the datatable for the dataviewgrid in the load function:
private void loadEmpresas(){
MySqlConnection myConn = new MySqlConnection(gVariables.myConnection);
MySqlCommand command = new MySqlCommand("Select codempresa as 'Codigo', nomempresa as 'Nombre empresa' from contabilidad.empresas", myConn);
try
{
MySqlDataAdapter sda = new MySqlDataAdapter();
sda.SelectCommand = command;
DataTable dbdataset = new DataTable();
sda.Fill(dbdataset);
BindingSource bSource = new BindingSource();
bSource.DataSource = dbdataset;
dataGridView1.DataSource = bSource;
sda.Update(dbdataset);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
the table in mysql looks like this:
SQL Table Image Link
so when it is running it shows this:
Now the problems that i have are that i have no idea how to modify the width of the columns, id like the entire table to cover that gray space and i want that on click it selects the entire row not just a cell. When it clicks the row i want to pupulate the rest of the textboxes but i have a problem with the click event which for testing purposes is this:
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
MessageBox.Show("clicked");
if (e.RowIndex >= 0)
{
DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex];
MessageBox.Show(row.Cells[0].Value.ToString() + row.Cells[1].Value.ToString());
}
else
{
MessageBox.Show("wat");
}
}
when I click it doesn't even show a messagebox sometimes, I seriously have no idea how to handle the click row event properly :C help please T_T
For updating the column widths try using DataGridViewColumn.width:
DataGridViewColumn column = dataGridView.Columns[0];
column.Width = 60;
DataGridViewColumn.Width property information.
To select the entire row you need to change the SelectionMode of the DataGrid to FullRowSelect:
this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.dataGridView1.MultiSelect = false;
SelectionMode information.
I doing a web page in asp.net and in a module have select a Excel archive with FileUpLoad and click in a button import. Hitherto I'm fine. But in the moment than I want select other Excel archive and click in the button import, don't clear the GridView and show error. I attempt with this because I see in other questions similar to this.
With this I load the Grid
Conn = string.Format(Conn, DireccionArchivo, MostrarHDR);
OleDbConnection ConnExcel = new OleDbConnection(Conn);
OleDbCommand CmdExcel = new OleDbCommand();
OleDbDataAdapter Oda = new OleDbDataAdapter();
DataTable Dt = new DataTable();
CmdExcel.Connection = ConnExcel;
ConnExcel.Open();
CmdExcel.CommandText = "SELECT * From ["Page1$"]";
Oda.SelectCommand = CmdExcel;
Oda.Fill(Dt);
ConnExcel.Close();
grdResultados.Caption = Path.GetFileName(DireccionArchivo);
grdResultados.DataSource = Dt;
grdResultados.DataBind();
And with this I want to clear the GridView and last y called of new the method of load the GridView
DataTable ds = new DataTable();
ds = null;
grdResultados.DataSource = ds;
grdResultados.DataBind();
The error than show me is in the grdResultados.DataBind(); when called the second time.
Just use null value:
grdResultados.DataSource = null;
grdResultados.DataBind();
I resolved the problem, in the moment than clear the GridView with
DataTable ds = new DataTable();
ds = null;
grdResultados.DataSource = ds;
grdResultados.DataBind();
this clear the GridView but dont clear the names of columns, and this was the error, also have to clean the names of the columns. To remove the columns:
for (int i = 0; grdResultados.Columns.Count > i; )
{
grdResultados.Columns.RemoveAt(i);
}
and in the method of load th GridView must be generate the columns automatically with this property:
grdResultados.AutoGenerateColumns = true;
I leave this in case anyone else has the same problem
try this
grdResultados.DataSource = null;
or
grdResultados.Rows.Clear();
then rebind the gridview
int gvHasRows = grdResultados.Rows.Count;
if (gvHasRows > 0)
{
grdResultados.Columns.Clear();
grdResultados.DataBind();
}
First check that there is data in the Gridview before trying to clear.
Rows has no Clear function.
If you use a Session clear the session Example:
DataTable ds = new DataTable();
ds = null;
GV.DataSource = ds;
GV.DataBind();
for (int i = 0; GV.Columns.Count > i; )
{
GV.Columns.RemoveAt(i);
}
ViewState["CurrentData"] = null;
Make an empty data table with just your column names and re bind
You can simply do this:
GridView1.SelectedIndex = -1;
If dataset IsNot Nothing AndAlso dataset.Tables.Count > 0 AndAlso dataset.Tables(0).Rows.Count > 0 Then
grid.DataSource = dataset
grid.DataBind()
Else
grid.DataSource = Nothing
grid.DataBind()
If you're using a XAML defined Grid, use this instead:
GridView1.Children.Clear();
GridView1.RowDefinitions.Clear();
GridView1.ColumnDefinitions.Clear();
I have a web part, in the createchildcontrols function it creates a gridview, calls a stored procedure and populates the grid view. One column of the gridView is a command field that has the key value for an item & is passed to another web part on the page to show the details. All was working fine until they wanted me to add a search capability to the list web part.
At first this appeared to work, the data in the columns sems to reflect correct search results, but the command field retains the orginal values when the page was first loaded with no search criteria.
Also, when doing the search it appears that it goes through the createchildcontrols function, populates gridview with all of the items, then runs through the code in the btnSearch_Click where more sql is run with the specific search criteria and the gridview
is re-bound with the search results (but orginal key values in command field).
Any ideas on how I've messed this up?
Code from CreateChildControls:
_view = new GridView();
this.Controls.Add(this._view);
_view.Caption = "Rate Quote Email";
_view.AutoGenerateColumns = true;
_view.DataKeyNames = new string[] { "XREF_ID" };
CommandField field = new CommandField();
_view.SelectedRowStyle.BackColor = Color.Red;
field.ShowSelectButton = true;
field.ButtonType = ButtonType.Link;
_view.Columns.Add(field);
_view.AllowPaging = true;
_view.PageSize = 20;
_view.AlternatingRowStyle.BackColor = Color.Cornsilk;
_view.PageIndexChanging += new GridViewPageEventHandler(_view_PageIndexChanging);
Code from btnSearch_Click:
DataSet ds = new DataSet();
rdr = cmd.ExecuteReader();
ds.Clear();
_view.DataSource = null;
ds.Load(rdr, LoadOption.PreserveChanges, "");
rdr.Close();
rdr.Dispose();
_view.DataSource = ds.Tables[0];
_view.DataBind();
DataSet ds = new DataSet();
ds.Clear();
rdr = cmd.ExecuteReader();
ds.Load(rdr, LoadOption.PreserChanges, "");
rdr.Close();
rdr.Dispose();
_view.DataSource = null;
_view.DataSource = ds.Tables[0];
_view.DataBind();
ds.Dispose();
cmd.Dispose();
conn.Dispose();