0

I am recoding a WinForms app (MySQL/EF6 with many fields to update) using WPF. I am examining code required to support INotifyPropertyChanged for each field, and wondering if this is an advantage over classic code behind event handling.

I have developed a robust WinForms app in C# supporting a fairly complex data model including EF6/MySQL. As you can imagine, with many text fields, combo boxes, NumUpDowns etc, there are many event handlers for all the different fields. As I look at moving this code base to WPF and its native data binding, I have read repeatedly about the need to recode your mid level data objects to support INotifyPropertyChanged on the setters for each field in your class.

I have already coded both screen setup methods and Winforms event handlers that perform bi-directional update capability between classes and controls. Of course these would require some modification to adapt to WPF control methods and properties. I'm trying to decide whether it's worth the coding effort and ongoing maintenance required to setup INotifyPropertyChanged on each individual field that interacts with the screen, or just modify the more classic code behind event handlers. I have between 50 and 100 fields (of various types), each of which would require special coding for bi-directional binding.

Is it worth it, or am I missing something as a WPF noob?

I have many, many fields in the existing data maintenenace classes that take this form:

public class clsLot
{
    // Code omitted for general error codes, enums etc.


    // Here are a long list of fields which are generated by EF6 model, decorated with straightforward {get; set; }
    public long idLot { get; set; }
    public string LotID { get; set; }
    public Nullable<long> idRecipe { get; set; }
    public string PlantOrder { get; set; }
    public Nullable<System.DateTime> CreateDate { get; set; }
    public string Inspector { get; set; }
    public string LotType { get; set; }
    [... Long list omitted.  For ease of maintenance when new fields are added to the database and ef6 model regened, this list is copied from ef6 gened code

            // maintenance methods omitted for mapping between this class and database (save, update etc.
    }

When I see examples of WPF two way binding, they say the class must support INotifyPropertyChanged, and that each field must be converted from the simpler "public string LotID {get; set;}" to something like this for each field

public class User : INotifyPropertyChanged
{
    // Begin modification for each field in the class that needs to be bi-directionally mapped
    private string _LotID;
    public string LotID 
    {
        get { return this._LotID; }
        set
        {
            if(this.name != value)
            {
                this._LotID = value;
                this.NotifyPropertyChanged("LotID");
            }
        }
    }
    // End of modification for each field

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        if(this.PropertyChanged != null)
        this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
}

I have no problem with adding the public event, and the NotifyPropertyChanged method to existing classes. My problem is the 13x expansion in the lines of code to support INotifyPropertyChanged for each field of which I have between 50-100 fields (and can no longer be copy/pasted from autogened classes created by Ef6 Model).

Is this worth it, vs. just moving and adjusting the existing screen setup and control event handler methods I have in the Winforms app?

The core of my problem is that I am working with autogened code that takes advantage of the "public string LotID { get; set;}" syntax, that would need to be broken down into separate private fields and public properties for each field/property that is presently autogened.

Charlie Peppler
  • 689
  • 1
  • 5
  • 6
  • You should implement INotifyPropertyChanged for properties that you want to use as the source of a WPF Binding, if the Binding is supposed to update its target property when the source property changes. – Clemens Jan 09 '19 at 14:54
  • There is a [difference](https://stackoverflow.com/q/295104/1997232) between fields and properties. – Sinatr Jan 09 '19 at 15:35
  • Possible duplicate of [Why use INotifyPropertyChanged with bindings in WPF?](https://stackoverflow.com/questions/10475130/why-use-inotifypropertychanged-with-bindings-in-wpf) – Sinatr Jan 09 '19 at 15:35
  • My apologies for not being precise in using the terms fields and properties. What I was referring to was the automatically generated code that combines the two as in "public string LotID { get; set; }" which combines the two into one as a short hand. The EF6 code generator uses this extensively, which drives the source of my question about undoing this scheme into its appropriate field/property model, and applying the INotifyPropertyChanged interface, and the getter/setters for each field/property. – Charlie Peppler Jan 09 '19 at 15:51
  • Have a look at [Fody.PropertyChanged](https://github.com/Fody/PropertyChanged). It can ease the burden of modifying all of your properties; all you need to do is add an attribute to the top of each class that implements `INotifyPropertyChanged`. Is it worth it? I think it is. – Robert Harvey Jan 09 '19 at 16:01
  • I just took a look at Fody, and it looks _very_ cool. I'm a little worried about adding the entire Fody build environment into Visual Studio. If it's such a big problem, at what point will MS just add Fody functionality into the existing VS build environment itself? – Charlie Peppler Jan 09 '19 at 17:33

1 Answers1

0

First of all, you can do the work using Find&Replace function of VS and some clever regex with one click.

Sceond of all, you forgot that you can delete all the event handlers, so in total some lines will be new, but some will be deleted.

From maintanance point of view, bindings and INPC are much more readable for humans and make it easier to solve problems like "Why this control does not show the current value?".

Can you also edit in ALL the code required to make two way sync for those properties using event handlers?

When using bindings, the xaml side is just Text="{Binding SomeStringProperty}" and it works.

** EDIT **

The main advantage is that you can use the MVVM pattern, which what WPF was designed for. That done right makes mantaining an app a lot easier, but in many cases more tedious.

Krzysztof Skowronek
  • 2,796
  • 1
  • 13
  • 29
  • I do understand that it is possible to create new automation software to modify existing code, however, that is still new software to write. My main worry is the amount of maintenance required should the database schema change (which is highly likely). Today, I use EF6 to autogen the classes that directly interact with the db, and if there is a change, I do a direct copy from the list of fields generated into my UI mapping class. I would need to then re-modify that list again each time there is a schema change. – Charlie Peppler Jan 09 '19 at 15:18
  • I do already have methods to update controls from the UI classes (which may require some mods, but is a one time effort), as well as VS generating event handling method shells with a click. I do get the simple XAML code, it's the bidirectional mapping code I worry about, and am trying to evaluate direction prior to starting. I'ld like to go one way or the other. – Charlie Peppler Jan 09 '19 at 15:22
  • the binding I showed works both ways for TextBox and most controls - which means property of the object changes when you write something in TextBox (may need to change trigger to `PropertyChange` if you don't want to wait until focus is lost) In some cases you need to specify `Mode=TwoWays`. Is that what you meant by bidirectional? – Krzysztof Skowronek Jan 09 '19 at 15:26
  • All this code is already being generated via EF6 with coding templates. Perhaps the folks that write the EF6 conversion template code (.tt files) could modify the template (or provide an optional template) to generate field definitions that include INotifyPropertyChanged code in the first place. – Charlie Peppler Jan 09 '19 at 15:32
  • I'm not completely up to speed on WPF syntax yet, but yes, my intention is Mode=TwoWays. In order to implement that, your UI model class needs to support INotifyPropertyChanged for each field, which is where my future code maintenance problem is. – Charlie Peppler Jan 09 '19 at 15:34
  • What you get from database are DTOs - Data Tranfer Objects. They should just have the properties that map to the columns and be as simple as possible. Then you have a class with the same properties, INPC interface and all the logic. You can copy data between them with tools like [AutoMapper](https://automapper.org/). Yes, that's a lot of boilerplate code. Yes, at first glance it's hard to maintain, but it makes life much more easy in the long run. That said, when working in WPF, you should really use MVVM pattern, to which this is essential. – Krzysztof Skowronek Jan 09 '19 at 15:37
  • I've been reading comments all over the place, and yes, the new XAML environment basically replaces WinForms control updates (Model->Control) and event handlers (Control->Model) with the need for lots of boilerplate INPC code in the Model itself. Since I was trying to automate as much of the Model code itself (derived from what you call DTOs), it seems the approach is either a) hand code the INPC mods for every field/Property b) use something like Fody (mentioned above...very cool but a lot of new infrastructure) or c) automate mods to Model code. I'm going to try c) using VS macro editor. – Charlie Peppler Jan 09 '19 at 17:40