Refresh BindingSource correctly - c#

I have a master-detail grid view on windows forms. I a very simple Repository (repo in code) that queries the database to get back DataTables.
At first I load the Data and define a relation like u see in the LoadData() method. Next, After I edit my Master table I want to refresh the view datasource. That's the unimplemented RefreshData(); method. If I'm refreshing after Edit I need the bindingsource not to lose the "current" row.
Here is the code:
public void LoadData()
{
//define the Bindingsource and 2 Datatables.
binder = new BindingSource();
tbTaxPayers = repo.GetTaxPayersDataTable(-1);
tbLinkedOrganizations = repo.GetTaxPayersLinkedOrganizations();
//create a dataset to define the relation so that the view can pick it up
ds = new DataSet();
ds.Tables.Add(tbTaxPayers);
ds.Tables.Add(tbLinkedOrganizations);
ds.Relations.Add("LinkedOrganizations", tbTaxPayers.Columns["CLI_ID"], tbLinkedOrganizations.Columns["LCC_CLI_ID_PARENT"]);
//set datasource to the main table.
binder.DataSource = tbTaxPayers;
view.LoadData(binder);
}
public void RefreshData()
{
// how to refresh without overhead ? and without losing focus if I just edit ?
}
EDIT:
By doing the next code it works but I have to create a new DataSet with every refresh. And it smells to me cause it almost a duplicate of my LoadData() method.
public void RefreshData()
{
tbTaxPayers = repo.GetTaxPayersDataTable(-1);
tbLinkedOrganizations = repo.GetTaxPayersLinkedOrganizations();
ds = new DataSet();
ds.Tables.Add(tbTaxPayers);
ds.Tables.Add(tbLinkedOrganizations);
ds.Relations.Add("LinkedOrganizations", tbTaxPayers.Columns["CLI_ID"], tbLinkedOrganizations.Columns["LCC_CLI_ID_PARENT"]);
binder.DataSource = tbTaxPayers;
}

Related

How to search or filter a column in C# datagrid view, datagridview source is a list

I use dapper to get a joined data from database, then store as a list, and use datagridview to display list,
Now I want to search a column by a textbox,
private void SetupDataTableAvailableTool() {
toolList = adapter.GetJoinedToolsData();
dgvAvailableTools.DataSource = null;
dgvAvailableTools.DataSource = toolList;
}
above code is display list in dgvAvailableTools.
List<Tools> toolFilterList = new List<Tools>();
BindingSource bs = new BindingSource();
bs.Filter = searchTextBox.Text;
dgvAvailableTools.DataSource = bs;
above solution is not working .
I tried below
(dgvAvailableTools.DataSource as DataTable).DefaultView.RowFilter =string.Format("Name='{0}'", searchTextBox.Text);
it give me an error Object reference not set to an instance of an object,
I tried to create datatable , but it is not working, code at below
DataTable dt = new DataTable("Products");
da.Fill(dt);
dataGridView.DataSource = dt;
can anyone tell me the solution? I dont need binding data to datagridview.
Thanks in advnace
When using a BindingSource filter you need to include the property name e.g. in this case Item is the property to filter on.
private void FilterButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(searchTextBox.Text))
{
_customerBindingSource.RemoveFilter();
}
else
{
_customerBindingSource.Filter = $"Item = '{searchTextBox.Text}'";
}
}
how can I transfer this list to BindingSource bs
The code above sets a DataTable to the BindingSource were in this case _operations.CustomerDataTable is returns a DataTable.
See this code for assignment
Code which reads the data
Werther using a DataTable or a DataAdapter its semantics.
See also BindingSource Filter with Starts, contains, ends with and case sensitive options

SQLite Data Adapter not displaying data

I'm trying to fill a data grid view in my windows form application but nothing is being returned from the database when I execute the select query. I've looked at other questions about this topic on this site but cannot find anything that addresses my problem.
The name of the data view table is qbcMemDataView and the data source is a sqlite dataset called sqlite_dbDataSet1
Here is the code I have in place:
public Form1()
{
InitializeComponent();
dbConnection = new SQLiteConnection("Data Source=sqlite_db.sqlite;Version=3");
dbConnection.Open();
string[] restrictions = new string[4];
restrictions[2] = "test_table_mom";
using (DataTable dTbl = dbConnection.GetSchema("Tables", restrictions))
{
for (int i = 0; i < dTbl.Rows.Count; i++)
{
tblChooser.Items.Add(dTbl.Rows[i].ItemArray[dTbl.Columns.IndexOf("TABLE_NAME")].ToString());
}
if (tblChooser.Items.Count > 0)
{
tblChooser.SelectedIndex = 0;
}
}
}
private void btnSelect_tbl_Click(object sender, EventArgs e)
{
string sql = "SELECT id, name FROM test_table_mom";
using (SQLiteDataAdapter dbAdapter = new SQLiteDataAdapter(sql, dbConnection))
{
DataTable dataTbl = new DataTable();
dbAdapter.Fill(dataTbl);
qbcMemDataView.DataSource = dataTbl;
}
}
Also, here is a screenshot of the program running that might help better explain the issue I am having: http://imgur.com/j9ffeVi
I know there is data inside the table, I just don't know why it is not appearing in the data grid when the btnSelect_tbl_Click method is executed.
Any help would be appreciated.
Thanks!
Per the tutorial How to: Bind Data to the Windows Forms DataGridView Control, you are missing a BindingSource component that binds the data from the datasource to your table to the DataGrid.
Initialize the BindingSource at the top of your class like so:
private BindingSource bindingSource1 = new BindingSource();
Then near the top of your button click method before the sql add the line:
qbcMemDataView.DataSource = bindingSource1;
and finally change the last line of code
qbcMemDataView.DataSource = dataTbl;
to
bindingSource1.DataSource = dataTbl;
try that and see if it works for you.
Note: I'm not sure if this applies to c# but maybe it's universal fix.
Android builtin adapters and such use _id as the name of the id field. The other problem is _id and id well it's not well documented in android.
About "_id" field in Android SQLite
You can use this technique renaming in the select but it gets messy and you may not catch all occurrences.
string sql = "SELECT id _id, name FROM test_table_mom";
My Opinion: Go back and refactor your db id to _id.

How connect adapter from view to model in MVP

Am not shure how to do this. Am litle confused, in my project c# winforms am using MVP pattern for deskotp application.
I have datagridview where i show products gorup. Database query for selecting products group is stored in model and that method for selecting return DataTable. Next, presenter call that model function for selecting and pass it to view. In view i put that DataTable in BindingSource and in gridview as DataSource i pass binding source.
This work good but what when i try to add new row in grid and try to save that new row?
What if i want to edit existing row and update that record to database.
If i want to create/update record from database i need to access to adapter and call update. Problem is becouse my adapter is in model not in view.
Am not shure how to from view access to adapter and dataset to model.
Check my code for selecting:
Model:
public DataTable SelectAll()
{
using (MySqlConnection conn = new MySqlConnection(Properties.Settings.Default.ConnectionString))
{
try
{
conn.Open();
string query = "SELECT Naziv, Opis FROM grupe";
using (MySqlDataAdapter adapter = new MySqlDataAdapter(query, conn))
{
dt = new DataTable();
ds = new DataSet();
adapter.Fill(ds, "grupe");
dt = ds.Tables["grupe"];
}
conn.Close();
}
catch(MySqlException ex)
{
MessageBox.Show(ex.Message);
}
}
return dt;
}
Presenter:
public DataTable SelectAll()
{
return _model.SelectAll();
}
View:
private void GrupeArtikala_Load(object sender, EventArgs e)
{
bs = new BindingSource();
bs.DataSource = _presenter.SelectAll();
groupDataGridView.DataSource = bs;
}
So now when i want to save changes to database i need to access to model database adapter but i dont know how.
private void saveToolStripButton_Click(object sender, EventArgs e)
{
changes = ds.GetChanges(); // DatSet changes is in model but i must access here but dont know how
if (changes != null)
{
int updatedRows = dataAdapter.Update(changes); // Adapter is in model and i need him here
ds.AcceptChanges();
}
}
Am not shure how to connect this to model to avoid mixing database queries in view forms.
Anyone can give me example to do this.
If I understand correctly, you need to call functions on objects belonging to your model, but you don't want your view to have a reference to your model. Is that right? If so, you could follow the pattern you used with the SelectAll function:
bs.DataSource = _presenter.SelectAll();
You are calling _presenter.SelectAll in the view, but ultimately getting the returned value from the model. So to call ds.GetChanges in your view, you could add a GetDataSetChanges function to your presenter:
public DataSet GetDataSetChanges()
{
return _model.GetDataSetChanges();
}
Same thing for calling update on your adapter. Add a function to the presenter:
public int UpdateAdapter(DataSet dataSet)
{
return _model.UpdateAdapter(dataSet);
}

c# clear datagridview bound to datasource

I have a datagridview bound to a datasource, all headers are added to the columns collection with a datapropertyname set.
When I clear the datagridview using
DataGridView1.DataSource = null;
The headers disappear also and when I fill the datagridview again the header texts are the database column names. How do I clear a bound datagridview without removing the headers?
You can use this
if (dataGridViewNotas.DataSource != null)
((DataTable) dataGridViewNotas.DataSource).Rows.Clear();
One of the approach to handle this issue is to use collection as data source,
Create a class with properties representing the data source (Each property would represent a column in the database)
public class Student
{
public string Name { get; set; }
public string Address { get; set; }
}
You need Add column to datagridview manually and set relevant DataPropertyName for each column and set the HeaderText. When you load the data from database first fill this data into a List. So you will have a List<Student>.
List<Student> studentDetail = new List<Student>();
Set this as the data source of the datagridview.
dataGridView1.DataSource = studentDetail;
Clearing Data source
To clear the data source of the Grid just create a empty Student list and set it as data source again. When you set like this header of each column will be retained.
List<Student> emptyStudentDetail = new List<Student>();
dataGridView1.DataSource = emptyStudentDetail;
If you do not want to use collection of objects and still refresh your data source using this.dataGridView1.DataSource = null; then try this approach:
Assuming you are using for data source either DataSet or local database. Each time before you bind the dataGridView with new data source, create unbound columns with the same names as the names of your data source. Once they are created, you should hide them, because they will be needed when you refresh dataGridView's data source. The following sample code is aware of the data source columns names and therefore they are hard coded, but you can loop each time through the data source and create new collection of unbound columns, if it is necessary.
private void Form1_Load(object sender, EventArgs e)
{
this.dataGridView1.DataSource = GetDataSet();
this.dataGridView1.DataMember = "Students";
this.dataGridView1.Columns.Add("unboundColumn1", "ID");
this.dataGridView1.Columns.Add("unboundColumn2", "Name");
this.dataGridView1.Columns["unboundColumn1"].Visible = false;
this.dataGridView1.Columns["unboundColumn2"].Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
this.dataGridView1.Columns["unboundColumn1"].Visible = true;
this.dataGridView1.Columns["unboundColumn2"].Visible = true;
this.dataGridView1.DataSource = null;
}
private DataSet GetDataSet()
{
DataSet dataSet = new DataSet();
dataSet.Tables.Add("Students");
dataSet.Tables["Students"].Columns.Add("ID", typeof(int));
dataSet.Tables["Students"].Columns.Add("Name", typeof(string));
dataSet.Tables["Students"].Rows.Add(1, "John Joy");
dataSet.Tables["Students"].Rows.Add(2, "Ivan Nova");
dataSet.Tables["Students"].Rows.Add(3, "Michael German");
return dataSet;
}
Struggled with this for 24 hrs. Not sure why it works, but the solution that did not produce a runtime error for me is to dispose of the table adapter associated with the datagridview:
if (this.dataTableTableAdapter != null)
{
this.dataTableTableAdapter.Dispose();
}

Refresh button - Refreshing data grid view after inserting, deleting, updating

I'm trying to create a refresh button to automatically refresh the data inside my datagridview after i have finish updating them.
However, my refresh button doesn't seem to work. The data displayed remains the same as the original one. It only gets updated after i manually end my windows app and rebuild it.
Here is my code:
private void button_refresh_Click(object sender, EventArgs e)
{
this.acuzioSecureStore_DatabaseXDataSet.AcceptChanges();
}
Please assist. thanks ^_^
The easiest way to handle this is to use a Binding Source object.
If your loading information into your DataGridView from an Access Database then your most likely storing the Data in a Dataset or DataTable.
Create a Binding Source object, and once you have populated your DataTable/Dataset, set the datasource for your Binding Source to your DataTable. Then set the Datasource from the DataGridView as the Binding Source object.
Doing this ensures that any changes in your datagridview or reflected in the DataTable and vice Versa. If you reload data into your DataTable it will reflect in the Data Grid Automatically.
DataTable dt = new DataTable();
BindingSource bs = new BindingSource();
bs.DataSource = dt;
dataGridView1.DataSource= bs;
All changes will now happen automatically.
Hey the solution above is good but when the above code is executed,the table disappears and is not seen. And if I execute
da.Fill(ds, "p");
dataGridView1.DataSource = ds.Tables["p"];
then whole table is created again.
private void button_refresh_Click(object sender, EventArgs e)
{
SqlConnection con=new SqlConnection(#"");
string query="select * from abc";
SqlCommand cmd=new SqlCommand(query,con);
SqlDataAdapter da=new SqlDataadapter(cmd);
DataTable dt=new DataTable();
da.Fill(dt);
dataGridView1.DataSource=dt;
}
I had a datagridview, bound to a table in an Entity Framework database:
dataGridView1.DataSource = MyDatabase.MyTable;
It would never refresh despite two wasted days.
I solved it with a simple workaround:
private void button_refresh_Click(object sender, EventArgs e) {
dataGridView1.DataSource = MyDatabase.MyTable.Where(i =>(true));
}
This is an ugly workaround, and friend explained me how it works - if I do just dataGridView1.DataSource = database.table, it will cache the table and use the cached data forever. The fact that each time we create a new dummy query, prevents .net from caching it.
Please try this, it worked for me and let me know if you have any better option.
private void button3_Click(object sender, EventArgs e)
{
dataGridView1.Refresh();
}
you Can Bind dataGridView On PageLoad or UserControl Load Event and After chage in grid view Call the Load Event
like
this.ucUsers_Load(null, null); // Windows From C#

Categories