Filling controls from a class [C#]

Solarion

Honorary Master
Joined
Nov 14, 2012
Messages
21,885
I've put this together. Watchyathink?

Code:
    class Utilities
    {
        public static void fillComboBox(ComboBox cmb, DataTable dt, String displaymember, String valuemember)
        {

            cmb.DataSource = null;
            cmb.Items.Clear();

            cmb.DataSource = dt;
            cmb.DisplayMember = displaymember;
            cmb.ValueMember = valuemember;

            DataRow dr = dt.NewRow();
            dr[displaymember] = "Select";
            dr[valuemember] = 0;
            dt.Rows.InsertAt(dr, 0);
            cmb.SelectedIndex = 0;
        }
    }

Code:
        private void FillClientCombo(int clientId)
        {
            dt = new DataTable();
            JobsBLL = new JobsBLL();

            dt = JobsBLL.GetClients();

            Utilities.fillComboBox(cboClient, dt, "ClientName", "Id");

            if (clientId > 0)
            {
                cboClient.SelectedValue = clientId;
            }   

        }
 
Last edited:

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
I have a couple of 'problems' with your implementation.
- PLEASE ditch DataTables. They are terrible to work with. Slow etc etc.
- You should not be newing the BLL here (in the form I assume this is). The business layer is a service and should be injected to decouple your form from the data source.
- You have to call FillCombo each time the data updates.
- If you want to seperate concerns, the form should not be getting the data from the BLL. It should only be presenting the data. Another class should be getting the data and making it available for presentation.

My suggestion is as follows (I tend to minimise code in the form down to only bindings and using DI):

Row represents the data you want to display in the combo:
Code:
  public class Row
  {
    public long Id { get; set; }
    public string Name { get; set; }
  }

The Viewmodel is where the behaviour behind the form is controlled from. The form is only the presentation/visualisation of the data/behaviour/state of the viewmodel behind it. The INotifyPropertyChanged allows controls on the form to bind to its properties. You inject the IBLL into the viewmodel, so you can inject any implementation (local DB, remote DB, Azure, webservice, anything) as a source of the data. When you call the UpdateRows, the viewmodel will fetch the data from the source and update the property. This will fire the event that will make binding happen.

Code:
 public class ViewModel:
    INotifyPropertyChanged
  {
    public ViewModel(IBll bll)
    {
      this.bll = bll;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public IList<Row> Rows
    {
      get { return rows; }
      private set
      {
        rows = value;
        OnPropertyChanged("Rows");
      }
    }

    public void UpdateRows()
    {
      Rows = bll.GetRows();
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) 
        handler(this, new PropertyChangedEventArgs(propertyName));
    }

    private readonly IBll bll;
    private IList<Row> rows = new List<Row>();
  }


Your form code is purely concerned with presentation. You can see the binding of the form Rows property to the viewmodel Rows property. Each time the viewmodel's Rows property is updated, the event will fire. This will in turn execute the form's Rows property setter and fill the combo.
Code:
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    public IList<Row> Rows
    {
      get {  return null; }
      set
      {
        //Fill Combo here
      }
    }

    public void CreateBindings(ViewModel dataContext)
    {
      this.dataContext = dataContext;

      DataBindings.Add("Rows", dataContext, "Rows", true, DataSourceUpdateMode.Never);
    }

    private ViewModel dataContext;

  }


To compose all of this you do this:

Code:
      Form1 frm = new Form1();
      Bll bll = new Bll();
      ViewModel dataContext = new ViewModel(bll);
      frm.CreateBindings(dataContext);
      
      Application.Run(frm);

You might think that is a lot more code than yours. Yes it is, but each class does one thing only. Its pulls the concerns apart and makes everything more extensible. You can now use any BLL implementation. In the same way you bind fiedl edit controls to properties in the viewmodel so that the behaviours, validation etc happens in the viewmodel and not the form.
 

Solarion

Honorary Master
Joined
Nov 14, 2012
Messages
21,885
Given me a hellova lot to think about there thanks Spacerat, I will start going through this, looks good!
 

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
Given me a hellova lot to think about there thanks Spacerat, I will start going through this, looks good!

Try it out by building a small little app using the above concepts. Then you flesh it out
 

Solarion

Honorary Master
Joined
Nov 14, 2012
Messages
21,885
Try it out by building a small little app using the above concepts. Then you flesh it out

Doing that now, a simple form with one Sql table. At some point the penny will drop, not yet though.
 

Hamster

Resident Rodent
Joined
Aug 22, 2006
Messages
42,923
I haven't done real C# work in quite a while, less so front end work, so forgive my possibly stupid question: I thought INotifyPropertyChanged only worked with WPF and not WinForms, or did that all change?
 

Necropolis

Executive Member
Joined
Feb 26, 2007
Messages
8,401
I haven't done real C# work in quite a while, less so front end work, so forgive my possibly stupid question: I thought INotifyPropertyChanged only worked with WPF and not WinForms, or did that all change?

You can use it wherever, just provides an interfaces for raising events when a classes properties get changed.


What you've done there is take a relatively simple concept and needlessly complicate it, imo.

Sure the concepts you espouse are valid - but you don't know within what context OP was going to be using the code he supplied here.
 

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
I haven't done real C# work in quite a while, less so front end work, so forgive my possibly stupid question: I thought INotifyPropertyChanged only worked with WPF and not WinForms, or did that all change?

INotifyPropertyChanged is the 'thing' that drives databinding in Winforms. Has done so from the beginning.
 

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
What you've done there is take a relatively simple concept and needlessly complicate it, imo.

It's actually not complicated. The responsibilities have been pulled apart to make it decoupled. More classes yes, but each has it's own role.

Well, you can implement any simple concept through code and make it work. It does not mean that the implementation is extensible or easily maintainable in the long run.

I am a BIG proponent of SOLID principles. The penny dropped when I read a DI book from Mark Seeman. Had many a-ha moments. It answered many questions I had and things that bothered me. My suggestions to OP come from that vantage point.

SOLID drastically reduces code complexity and as a result improves code quality and extensibility. If you are just knocking something together then yes, do a quick and dirty. But if you are developing software intended for a production environment, it needs to have much better quality than a knocked-together app. Also, you know it's going to change, so design it such that it is easy to maintain and extend. Maintainability and extensibility is a design goal. Not something you think about after the fact. So, establishing patterns in how you have designed your app, and reducing the amount of code will make your app less complex and easier to understand.

Sure the concepts you espouse are valid - but you don't know within what context OP was going to be using the code he supplied here.

Agreed, if the OP just wanted an opinion on a small bit of code then yes, my suggestions are over the top. But I came from the understanding that OP is possibly in the early stages of designing/building an app. SO I offered a few ideas. Use it or don't.
 

Necropolis

Executive Member
Joined
Feb 26, 2007
Messages
8,401
SOLID drastically reduces code complexity and as a result improves code quality and extensibility. If you are just knocking something together then yes, do a quick and dirty. But if you are developing software intended for a production environment, it needs to have much better quality than a knocked-together app. Also, you know it's going to change, so design it such that it is easy to maintain and extend. Maintainability and extensibility is a design goal. Not something you think about after the fact. So, establishing patterns in how you have designed your app, and reducing the amount of code will make your app less complex and easier to understand.

Can't argue with you there :)
 

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
Doing that now, a simple form with one Sql table. At some point the penny will drop, not yet though.

Let me know if you need help or explanation of how it works... I C&P the code quickly. I could create a compilable app if you need help.

Once you have populated the combo from the VM, then you can actualy start binding textboxes etc to the VM as well. Data you enter then automatically propagates from form to VM. No copying between textbox and VM needed. That is what one way and two databinding is for. If a value changes in the VM then it automatically propagates to the textbox without you having to do anything.

Then the fun starts when you bind your buttons to the VM as well. The VM then controls the button state and caption and hint etc. And the button executes commands in the VM. Just like WPF.

So the form code ends up being just setting up bindings. All behaviour is handled by VM. What I like about this is that the VM represents the view. It does not know or care what controls the form use for presentation or what kind of button the form uses to invoke commands. It also interacts with the layers further down so that the form is totally abstracted from where the data comes from and what structure it has. The other advantage in having all data and behaviour in the VM, is that if you follow TDD, then you can write automated tests that invoke commands in the VM and validates the data it see. See a diagram here http://mybroadband.co.za/vb/showthr...k-required?p=17705734&viewfull=1#post17705734
 

Solarion

Honorary Master
Joined
Nov 14, 2012
Messages
21,885
Let me know if you need help or explanation of how it works... I C&P the code quickly. I could create a compilable app if you need help.

Once you have populated the combo from the VM, then you can actualy start binding textboxes etc to the VM as well. Data you enter then automatically propagates from form to VM. No copying between textbox and VM needed. That is what one way and two databinding is for. If a value changes in the VM then it automatically propagates to the textbox without you having to do anything.

Then the fun starts when you bind your buttons to the VM as well. The VM then controls the button state and caption and hint etc. And the button executes commands in the VM. Just like WPF.

So the form code ends up being just setting up bindings. All behaviour is handled by VM. What I like about this is that the VM represents the view. It does not know or care what controls the form use for presentation or what kind of button the form uses to invoke commands. It also interacts with the layers further down so that the form is totally abstracted from where the data comes from and what structure it has. The other advantage in having all data and behaviour in the VM, is that if you follow TDD, then you can write automated tests that invoke commands in the VM and validates the data it see. See a diagram here http://mybroadband.co.za/vb/showthr...k-required?p=17705734&viewfull=1#post17705734

Thanks Spacerat. Perhaps I could send you the code of what I have put together? It's a WinForm demo with 4 forms, a job card system in C# I would be really grateful if you would take a look and see what you think, or even chop and change it around to give me a starting point? What you posted earlier looks pretty awesome. I have reached a point now with n-tier/separation of concers where I have kind of hit a wall and wanting to go further.

I totally forgot about that thread, Will have a gander at it.
 

Spacerat

Expert Member
Joined
Jul 29, 2015
Messages
1,328
Thanks Spacerat. Perhaps I could send you the code of what I have put together? It's a WinForm demo with 4 forms, a job card system in C# I would be really grateful if you would take a look and see what you think, or even chop and change it around to give me a starting point? What you posted earlier looks pretty awesome. I have reached a point now with n-tier/separation of concers where I have kind of hit a wall and wanting to go further.

I totally forgot about that thread, Will have a gander at it.

sure. pm me a link
 
Top