In my C# project, i populated the values in DataGrid from DataTable. Now if i make changes in the values in the DataGrid i need to update them in the DataBase. I'm using MS access.
Here is the code snippet of how i populate values in the DataGrid.
while (myReader.Read())
{
frmBind.dr = frmBind.dtResults.NewRow();
frmBind.dr["ClassName"] = myReader.GetString(0);
frmBind.dr["MethodSignature"] = myReader.GetString(1);
frmBind.dr["ParameterValues"] = myReader.GetString(2);
frmBind.dr["ExpectedResults"] = myReader.GetString(3);
frmBind.dtResults.Rows.Add(frmBind.dr);
}
frmBind.dataGrid2.DataSource = frmBind.dtResults;
where,
dtResults is DataTable,
frmBind is a Class Object,
dataGrid2 is the DataGrid,
myReader.Read() is used to get the values from the DataBase.
I suggest you drop the datareader.
Drag an SQLDataSource onto the page and configure it with your query. It will give you reading/updating without writing any code at all.
Related
My end goal is to populate a DataGrid with data retrieved from a database at runtime. My methodology is to pull all the columns from that database first and then pull the corresponding data for each column for each row as below:
ReadOnlyCollection<Field> tablefields = {//has the fields populated from the database};
//adding all the columns to the data table
var datatable = new DataTable("mytable");
foreach (var field in tablefields)
{ datatable.Columns.Add(field.Name, wFieldType); }
//Then add the rows
while (cursor.MoveNext())
{
var tableRow = datatable.NewRow();
var row = cursor.Current;
for(var i = 0; i < tablefields.Count; i++)//add the values for each field to the data table.
{
tableRow[i] = row[i] ?? DBNull.Value;
}
datatable.Rows.Add(tableRow);
}
My problem however is that some of the columns that I am pulling have to be in the form of a DataGridComboBoxColumn since they have preset values in a dropdown list in the database. The best case scenario would have been that as I pull the columns into my dataTable one by one, I would detect the ones that have preset values and make those oftype DataGridComboBoxColumn before adding them to the dataTable. I obviously can't do that because you cannot have a combobox on a dataTable. My next option is to use the dataGrid to load the columns and the data from the database at runtime.
I am able to add the columns with a combobox as shown in the code below but I cannot figure out how to get my data from the database into the dataGrid containing the pre-loaded columns.
DataGridComboBoxColumn cb = new DataGridComboBoxColumn();
cb.ItemsSource = new List(){to be populated later}
cb.Header = field.Name;
MyDataGrid.Columns.Add(cb);
The code above was used as a sample to test the DataGridComboBoxColumn and sure enough I was able to see the datagrid with the comboboxes. I just can't figure out how to get my database data into the table. I would appreciate any ideas.
PS: I cannot use datagridview because of the api that I am working with so I am limited to datagrid.
You should set the SelectedItemBinding to a binding to a column in your DataTable that contains the value in the ItemsSource to be selected:
cb.SelectedItemBinding = new Binding("AColumnInYourDataTable");
If you set the ItemsSource to a List<T> where T is a complex type, you should instead set the SelectedValueBinding and SelectedValuePath and DisplayMemberPath properties:
cb.SelectedValueBinding = new Binding("AColumnInYourDataTable");
cb.SelectedValuePath = "NameOfThePropertyOfTThatHoldsTheValue";
cb.DisplayMemberPath = "NameOfAPropertyOfTThatHoldsTheDisplayName";
I try to pass data from grid control in dev express to database
I try with this code but make an error.
var items = gridView1.DataSource;
foreach (var row in items)
{
row.Invoice_ID = invoice.ID;
row.Trip_ID = tr.ID;
db.Invoice_Details.InsertOnSubmit(row);
You need to specify the datasource of the grid control. Not the Grid view.
1. Get data from your database then put it into a datatable.
2. Use Gridcontrol.datasource = datatable
I have a Winform application which is almost working, but is becoming increasingly complex around the way users update and insert data via DataGridViews, and how this is fed back into the List in the background. Currently both DataGridView's are populated from a single List, and when a user updates a cell, the List is then updated from the Grid. I'd prefer to use the List as a DataSource.
Very simplified dataset (Server, Function, Proces) - P.S. I can't change my data set:
Server1, KeepAlive, SQLService
Server1, KeepAlive, AnotherProcess
Server1, Kill, RogueProcess
Server2, KeepAlive, SQLService
Server3, KeepAlive, SQLService
DataGridView1 has 1 column containing Distinct server names and DataGridView2 has 2 columns containing all functions and processes for the selected server in DataGridView1. A user can edit any cell and currently I keep track of each change and reflect it back into the List, then refresh the Grids. I'd prefer to handle this using the DataGridView DataSource object.
My question's are: What is the most suitable data source setup (I.e. a List of objects)? How do I filter differently from the data source into the Grid's?
So far I've tried the following. Create a Config class:
class Config
{
[DisplayName("Server")]
public string server { get; set; }
[DisplayName("Function")]
public string function { get; set; }
[DisplayName("Process")]
public string checkType { get; set; }
}
Create a List which contains these Config objects:
List<Config> configurations = new List<Config>();
Assign the List as a Data Source:
dataGridView1.DataSource = configurations;
This displays all three columns of data as expected. How can I a) show only the Server column and b) show only a distinct list?
I'm guessing with DataGridView2 I can use RowFilter to display only the selected server:
(dataGridView2.DataSource as DataTable).DefaultView.RowFilter = ?
Thanks in advance for any help!
Edit
I have tried using LINQ:
dataGridView1.DataSource = configs.Select(o => new { Server = o.server }).ToList();
This worked, but my grid was read-only, so I used a custom view model too:
dataGridView1.DataSource = configs.Select(o => new ServerView() { Server = o.server }).ToList();
This is displaying exactly how I want, but when I edit a cell, the change is not reflected in the List. Can LINQ be used with DataSource like this?
Edit 2
Using stefankmitph's examples I can filter via a SortableBindingList:
SortableBindingList<Config> sortableBindingList = new SortableBindingList<Config>(configs.Where(o => o.server == "Server1").ToList());
BindingSource bindingSource = new BindingSource(sortableBindingList, null);
dataGridView1.DataSource = bindingSource;
This resolves the issue for DataGridView2 which needs to be filtered based on what is selected in #1. However, I still can't work out how to only display certain columns in the grids. #1 should have only the servers and #2 should have the remaining two columns. A select in the LINQ query wouldn't work because I'm dealing with a Config object ... right?
Over the years I've struggled with a lot of problems with the DataGridView. Here's just what for me is 'best practice':
1a) I most often attach my data (List) to a SortableBindingList (there's a lot of examples out there here, here and here. Take what fits you.)
Assuming there's a List configurations;
dataGridView.DataSource = new SortableBindingList<Config>(configurations);
now your DataGridView is sortable.
1b) When it comes to filter the DataSource there's a bunch of options. As far as I'm concerned the filtering only applies to the BindingSource with a DataTable attached as DataSource
Assuming there's a DataTable dataTableConfigurations:
BindingSource bindingSource = new BindingSource(dataTableConfigurations, null);
dataGridView.DataSource = bindingSource;
bindingSource.Filter = "Server = 'Server3'";
but I'm quite sure that this won't work with a List of objects as DataSource.
What you can do:
SortableBindingList<Config> sortableBindingList = new SortableBindingList<Config>(configurations);
BindingSource bindingSource = new BindingSource(sortableBindingList, null);
dataGridView.DataSource = bindingSource;
This way it's very easy to track changes in your data. (f.e. BindingSource.Current returns the current item of your DataGridView)
BindingSource bindingSource = dataGridView.DataSource as BindingSource;
Config currentConfig = bindingSource.Current as Config;
If I would have to filter the data now, I'd do the following:
BindingSource bindingSource = dataGridView.DataSource as BindingSource;
List<Config> list = bindingSource.DataSource as List<Config>;
bindingSource.DataSource = list.Where(item => item.Server = 'banana').ToList();
If you have any bindings to the BindingSource (TextBoxes, ComboBoxes, etc.) keep in mind that attaching/detaching DataSource can cause unwanted behaviour. To avoid this I do suspending and resuming of the binding:
bindingSource.SuspendBinding();
// do the filtering
bindingSource.ResumeBinding();
This keeps all the DataBindings alive.
UPDATE: displaying only certain columns in your DataGridView
That's quite simple. (column names correlate with the names in your DataSource object)
var columnFunction = dataGridView.Columns["function"];
if(columnFunction != null)
columnFunction.Visible = false;
var columnCheckType = dataGridView.Columns["checkType"];
if(columnCheckType != null)
columnCheckType.Visible = false;
So only your server column will be displayed.
I have table in my database stored in SQL Server 2012 and through this table I am iterating and adding new object in my binding list. This list is then set as datasource for my DataGridView.
As I understand, the DataGridView should create columns and fill the rows with data, but when I run the build, I only see blank rows. Their count is matching the count of rows in table and I also debugged with breakpoints so I have determined that I really have my datasource filled with data, but I cannot figure those blank rows out.
This is method I use for creating dataset and filling the binding list
public void selectCars()
{
string connString = #"Data Source=POHJOLA\SQLEXPRESS;Initial Catalog=BlueCars;Integrated Security=True";
using (SqlConnection connection = new SqlConnection(connString))
{
connection.Open();
string query = "SELECT * FROM Car ORDER BY CarID ASC";
SqlCommand command = new SqlCommand(query, connection);
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
using (DataSet result = new DataSet())
{
adapter.Fill(result);
foreach (DataRow row in result.Tables[0].Rows)
{
carsList.Add(new Car(Convert.ToInt32(row[0]), row[1].ToString(), row[2].ToString(), row[3].ToString(), Convert.ToDecimal(row[4]),Convert.ToInt32(row[5]),row[6].ToString(),row[7].ToString() ));
}
}
}
}
This is my initialization
public managerCarForm()
{
InitializeComponent();
selectCars();
carsGrid.DataSource = carsList;
}
Also I should probably add, that I created columns manually in designer and set datanameproperty to parameters of the car class
I am not getting any exception or error here..
Thanks very much in advance!
I came across the exact same problem in VB.
I Found out that the solution was this:
(I´ll just write my code in VB you can translate it).
Before setting the DataSource of the grid, you should Clear the grid out.
carsGrid.DataSource = Nothing
carsGrid.Rows.Clear()
carsGrid.Columns.Clear()
Then set your grid DataSource as usual. In My case:
carsGrid.DataSource = GetEmptyObject._Get()
Hope it Helps.
foreach (DataRow row in result.Tables[0].Rows)
{
carsList.Add(new Car(Convert.ToInt32(row[0]), row[1].ToString(), row[2].ToString(), row[3].ToString(), Convert.ToDecimal(row[4]),Convert.ToInt32(row[5]),row[6].ToString(),row[7].ToString() ));
}
Please check your carList by applying a breakpoint after foreach loop to verify it contains at least a single data row. And also check your query.
If your application is an ASP.NET
try to modify your code as below..
public managerCarForm()
{
InitializeComponent();
selectCars();
carsGrid.DataSource = carsList;
carsGrid.Databind();
}
Normally this happens when you have manually added the columns in design time.
Or you have AutoGenerateColumns = false;
If you use AutoGenerateColumns = true; the columns will be/should be auto generated.
To solve this:
Right click on the grid -> Edit Columns.
Go to property: DataPropertyName
Set that to the variable name that you bind to (the table column name in your case).
(You say you have done that, but the value here should exactly match what you have in your list. I have made a DTO class and via a loop I have populated a List of my own and set the names to match the properties of that DTO. This should solve it for you.)
I load my data into a GridView using DataSet. At first databinding, it works well. But when I run query that return different columns, the GridView show the new column plus the old one. I've tried the gridView1.Columns.Clear() method, but it doesn't solve the problem.
Here are some of the code:
// loading data into dataset
dataSet dsGrid = new dataSet();
string dtMember = "kpi";
// note: "thequery" is query generated based on user's selection
using (MySqlDataAdapter da = new MySqlDataAdapter(thequery, myCn))
{
da.Fill(dsGrid, dtMember);
}
// set the gridControl's datasource
gc_report.DataSource = null;
// clear the columns
gridView1.Columns.Clear();
// bind the data
gc_report.DataSource = dsGrid;
gc_report.DataMember = dtMember;
When I run my application, it runs well, but if the query return different column, the old column still appear although I've put the Clear() method of the gridView1.Columns collection.
How to set the gridView1 , so the grid always shows the current query?