4

I have added a record to the underlying db and after I add the record i do a datagridview.Refresh(); and i dont see the newly added record.

If i stop and start the application its there. What am I doing or not doing? Notes : button1 and datagridview is in different Forms.I made datagridview's Modifiers public. This project is ado.net project

public class CustomerService
{
    public List<Customers> ShowAll()
    {
        List<Customers> customers = new List<Customers>();
        SqlConnection conn = new SqlConnection("data source=.; database=custer; user id=sa; password=*****");
        SqlCommand cmd = new SqlCommand(" select * from Customers ", conn.Open());
        SqlDataReader dr = cmd.ExecuteReader();
        while (dr.Read())
        {
            Customer customer = new Customer ()
            {
                CustomerID = dr.GetInt32(0),
                CustomerName = dr.GetString(1),
                CustomerSurname = dr.GetString(2),
            };
            customers.Add(customer);
        }
        conn.Close();
        return customers;
    }
  }

    private void button1_Click(object sender, EventArgs e)
    {
        CustomerService service = new CustomerService();
        if (txtCustomerName.Text != "" || txtCustomerSurname.Text != "")
        {
            customerservice.customerAdd(txtCustomerName.Text, txtCustomerSurname.Text);//this rows is other method .I am using for adding new customer 
            MessageBox.Show("Customer Added");
            Form1.dataGridView1.DataSource = service.ShowAll();
            Form1.dataGridView1.Refresh();
        }
        else
        {
            //……………
        }
    }
  • What does "musteriservice.MusteriEkle(txtCustomerName.Text, txtCustomerSurname.Text);" do? – BugFinder Aug 13 '12 at 14:10
  • musteriservice is other method .I am using for adding new customer –  Aug 13 '12 at 14:23
  • Are you even sure that your query is working..? have you stepped into the code using the Debugger..?? – MethodMan Aug 13 '12 at 14:33
  • Is there any chance your adding is not happening in time before the refresh? – BugFinder Aug 13 '12 at 14:36
  • @DJKRAZE yes it is working.but I cant see datas at that time in dataGridView –  Aug 14 '12 at 06:55
  • @bugfinder I dont understand what you mean ? can you open a little more ? –  Aug 14 '12 at 06:56
  • If you submit the request for the data to be added, but it hasnt completed by the time you request the refresh then you wont see it in your list. – BugFinder Aug 14 '12 at 08:44
  • Thanks for your answers.But it must be a way to see data at that time.Where I am doing mistake ? –  Aug 14 '12 at 08:50
  • have you thought about Binding to the DataGrid Form1.dataGridView1.DataSource = service.ShowAll(); Form1.dataGridView1.BindData; – MethodMan Aug 16 '12 at 20:42
  • `If i stop and start the application its there` - show us that code, the Form_Load method? I also wonder if you have AutoGenerateColumns = false or is it true? @DJKRAZE You dont need the `BindData` for winforms - you do for asp.net. – Jeremy Thompson Aug 20 '12 at 05:14
  • Post the code that loads the data on the first start of the application, curious how/if it's different from your button1_click. Moreover, you could likely add the record directly by adding a member to the Rows list. I don't think Refresh() is for the datasource, I think it's for the UI (in case you changed the value of a label or etc). Usually you update datasource by some form of bind event (you might have to refresh after executing said bind event). If it's WPF try looking for a NotifyCollectionChanged event to fire. – Jimmy Hoffa Aug 22 '12 at 02:00
  • You could use a BindingList instead of List...or... wrap your List with a BindingSource and use ResetBindings to get the data reloaded...or... stick to the List and reset the DataStore like this.....Form1.dataGridView1.DataSource = null; Form1.dataGridView1.DataSource = service.ShowAll(); – Colin Smith Aug 22 '12 at 13:12

12 Answers12

3

After adding the data to the DB, your application knows nothing about the data added. You need to load those data to memory. Retrieve all the data you want to display from the database and bind it explicitly to UI after doing operations on database.

EDIT:

Can you check what ShowAll() returns while debugging? Does it return you the data you actually want?

If it is a WPF application take a look here. The issue here is to tell your UI component that underlying data source has been changed, so the UI component reflects the changes made to data.

Again if it is a WPF application, you can define your data as ObservableCollection and bind you UI to this collection. ObservableCollection automatically requests UI to refresh when data has changed.

Rica ederim .)

Mert Akcakaya
  • 3,109
  • 2
  • 31
  • 42
  • teşekkürler.But this is not web application.I tried to use databind but not worked. –  Aug 14 '12 at 07:25
  • I understood what is problem but I didn't understand how to solve.by the way ShowAll() returns customers.I checked it –  Aug 14 '12 at 08:40
2

The usual way of doing this is to reset the DataSource of the DataGridView.

Try like this code (with correct code to provide the right datasource):

Form1.dataGridView1.DataSource = typeof(List); 
Form1.dataGridView1.DataSource = service.ShowAll();

Calling .Refresh() doesn't work since it only forces a repaint, but the code that paints the grid doesn't know of the changes.

Ref this WPF link also, that may help you:

Why does the DataGrid not update when the ItemsSource is changed?

Community
  • 1
  • 1
Niranjan Singh
  • 18,017
  • 2
  • 42
  • 75
  • Your code snippet first assigns the property to a System.Type object and then assigns the property to a List object, the first assignment is completely redundant. – Jimmy Hoffa Aug 22 '12 at 02:02
1

Try calling EndEdit on the datagridview:

this.dataGridView1.EndEdit();

Second, refresh the grid view:

this.dataGridView1.Refresh();

And if that still doesn't work, try calling Refresh on the containing control

ParentControl.Refresh()

This will end up calling a repaint that might be needed.

Josh
  • 10,352
  • 12
  • 58
  • 109
1

what is the content of customerservice.customerAdd ? Maybe it doesnt close the connection properly/doesnt flush the data into the db,and it only happens when you close your app(all memory is disposed,and all connections are closed/flushed).

Also - I suggest using a BindingSource that the grid is bound to,and changing its data source - it has event to notify the grid automaticallly if its data source has changed and that will cause it to refresh.

yonigozman
  • 707
  • 8
  • 15
  • this is ado.net project.I used entity-facade in my project named model-service...I defined CustomerAdd method into customerservice .that's why I wrote customerservice.customerAdd(...) –  Aug 16 '12 at 12:28
  • yes,i understand that,but can you please post the contents of the CustomerAdd method? – yonigozman Aug 16 '12 at 16:32
  • also - did you try using a BindingSource like i suggested? – yonigozman Aug 16 '12 at 16:34
1

As you said these are in different forms, I think the pointer to Form1 doesn't point to the form that you want. you should pass the pointer of that form with this to this form.

When you are creating form 2 define like this:

Form2 = new Form2();
Form2.form1 = this; 

Then your code should work.

Hamed
  • 2,084
  • 6
  • 22
  • 42
1

It appears you're using a List as the datasource. I've found using a generic list is ok for read only data but for doing any kind of updates you need something with more power. I don't know about WPF but in winForms I've had great success with the IBindingList interface and the BindingList generic collection. The BindingList generic collection implements the IBindingList interface for you. I would read the MSDN articles on both of them. I've pretty much stopped using the IBindingList interface but it's still perfectly fine to implement.

http://msdn.microsoft.com/en-us/library/system.componentmodel.ibindinglist.aspx

http://msdn.microsoft.com/en-us/library/ms132679.aspx

Justin
  • 4,002
  • 2
  • 19
  • 21
1

The answer is to have the gridview connected to the BindingList<Customers> rather than the List<Customers> . Hope this will solve your problem...

Krishnakumar
  • 266
  • 2
  • 7
1

If you change the List to a BindingList you'll have success. I threw together a sample which just had a DataGridView and a couple of Buttons on a Form.

button1 generates some fake data and assigns the datasource. button2 adds another Customer to the underlying list.

The DataGridView is updated when the underlying BindingList changes.

Code:

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string SurName { get; set; }
}

public partial class Form1 : Form
{
    BindingList<Customer> customers = new BindingList<Customer>();
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 10; ++i)
        {
            customers.Add(new Customer
            {
                Id = i,
                Name = "Name" + i,
                SurName = "Surname" + i
            });
        }
        dataGridView1.DataSource = customers;
    }

    private void button2_Click(object sender, EventArgs e)
    {
        customers.Add(new Customer
        {
            Id = 22,
            Name = "Newname",
            SurName = "Newsurname"
        });
    }
}

Now, the reason this works is that BindingList<T> implements IBindingList, among other things, and that interface has, among other things, an event called ListChanged which is raised when the list or something in the list changes.

itsmatt
  • 31,265
  • 10
  • 100
  • 164
1

If you are not bound to use customer list strictly as data-source for datagridview then Here is much better solution using datatable. You will get updated customer list and datagridview after insert

public class CustomerService
{
  public DataTable ShowCustomers()
  {
    string cns = "data source=.; database=custer; user id=sa; password=*****";
    SqlConnection conn = new SqlConnection(cns);
    SqlDataAdapter da = new SqDataAdapter("select * from Customers", conn);
    DataTable dt = new DataTable();
    da.Fill(dt);
    return dt;
  }
}    
private void button1_Click(object sender, EventArgs e)
{
   CustomerService service = new CustomerService();
   if (txtCustomerName.Text != "" || txtCustomerSurname.Text != "")
   {
     customerservice.customerAdd(txtCustomerName.Text,txtCustomerSurname.Text);
      MessageBox.Show("Customer Added");
      DataTable dt = service.ShowCustomers();
      Form1.dataGridView1.DataSource = dt;
      //If you also need customer list. Provide the DataTable and get list
      List<Customers> customers = new List<Customers>();        
      for (int i=0;i<dt.Rows.Count;i++)
      {
        Customer customer = new Customer();            
        customer.CustomerID = Convert.ToInt32(dt.Rows[i][0]);
        customer.CustomerName = dt.Rows[i][1].ToString();
        customer.CustomerSurname = dt.Rows[i][2].ToString();
        customers.Add(customer);
      }
   }
}
Sami
  • 8,168
  • 9
  • 66
  • 99
  • Having any issue with Efficiency? I am there and can tell a much more efficient and accurate way, fully fulfilling your requirements as well. just want to know if you are still following it. – Sami Aug 22 '12 at 21:08
1

You need to do data binding only once not on every new record. That's the whole point of binding data to a control that all changes will be auto reflected.

  1. Make customers a data member of the CustomerService class and change your code appropriately:

    class CustomerService {
        List<Customers> customers;
        ...
    }
    
  2. Next the binding code should be done once, maybe when the first record is added to the List<Customers>.

    BindingSource binding = new BindingSource();
    binding.DataSource = customers;
    dataGridView1.DataSource = binding;
    

If you have done this right, every time any record is deleted or added to the customers collection, it should be automatically be reflected in the DataGridView control.

M. Ahmad Zafar
  • 4,881
  • 4
  • 32
  • 44
1

I think you must have used update panel and might not refreshing that

user1562231
  • 241
  • 1
  • 5
  • 12
1

I think this will solve your problem, Check this........

DataGrid.CommitEdit();
DataGrid.Items.Refresh();

NOTE

CommitEdit() method will fire the RowEditEnding event, it is a endless loop. WPF does not allow to refresh the view while it is editing, since it may occur the endless loop. However, you could refresh the view after editing. Try to remove the RowEditEnding event handler (If Initialzed) , and do refresh for the Items; Then add the event handler back:

Pintu Paul
  • 389
  • 3
  • 18
  • Use [observablecollection](http://msdn.microsoft.com/en-us/library/ms668604.aspx) instead of list. tht will solve your problem of updation in list. – Pintu Paul Oct 24 '12 at 13:06