0

I've applied the MVVM pattern in c# using Windows Forms. In the View (MainForm) I bind a DataGridView "InstalledChartsView" to a DataTable "ChartTable".

 BindingSource binding = new BindingSource
 {
     DataSource = m_ViewModel.ChartTable
 };

 InstalledChartsView.DataSource = binding;

This ChartTable is part of the "Charts" class created in the ViewModel:

    private Charts m_Charts;
    public DataTable ChartTable
    {
        get { return m_Charts.ChartTable; }
        set
        {
            m_Charts.ChartTable = value;
            NotifyPropertyChanged("ChartTable");
        }
    }

Now what really should be happening is that m_Charts (the model), a thread is running that is continuously updating this ChartTable from an online database. The DataTable gets updated correctly, but the gridview does not.

However, for testing, I'm not even touching the model, but doing some stuff from the view (MainForm). I'm continuously running the following thread and weird stuff happens there.

  new Thread( () =>
        {
            for ( ; ; )
            {
               m_ViewModel.AddRow("b", "b", "b", "b");

                //Some unrelated stuff happens here.
                try
                {
                    BeginInvoke( (Action) ( () =>
                    {
                        m_ViewModel.AddRow("a","a","a","a");
                    }
                 }
                 catch{};
                 Thread.sleep();
             }
         }

Now both "AddRow" comments get executed more or less correctly: a row is added to the table in the model. However, the view ONLY gets updated at the aaaa statement! At that time BOTH rows get shown correctly.

This is my addRow method:

       public void AddRow(string a, string b, string c, string d)
    {
        m_Charts.ChartTable.Rows.Add(a, b, c, d);
        NotifyPropertyChanged("ChartTable");
    }

Can anyone shed some light on why NotifyPropertyChanged works correctly in one case, but not in the other?

Tessa
  • 297
  • 1
  • 3
  • 10

1 Answers1

1

Updates to UI controls must happen on the UI thread in order for the controls to update themselves.

While you may have updated the collection with the "b" call, the "a" call was on the correct thread so then caused the UI to update.

There are ways to check within the WinForms View that updates are occurring on the correct thread - have a look at the answer to this question for an example: Automating the InvokeRequired code pattern

Community
  • 1
  • 1
toadflakz
  • 7,764
  • 1
  • 27
  • 40
  • Toad beat me to it. I was just typing something similar to those lines. – James Shaw Dec 11 '14 at 16:42
  • Does that mean that if I want to do something in a thread in my model class, I have no way of updating my view? As that will never be on the UI thread, and the model class should have no direct access to the view... – Tessa Dec 12 '14 at 07:48
  • Not necessarily. I think you may be working with the wrong type of notification for WinForms. You need to use BindingList and IRaisePropertyChanged derivative types. http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.datasource(v=vs.110).aspx – toadflakz Dec 12 '14 at 09:34