• (2 Pages)
  • +
  • 1
  • 2

Separating data from GUI - PLUS - serializing the data

#16 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3631
  • View blog
  • Posts: 11,327
  • Joined: 05-May 12

Posted 01 June 2012 - 01:13 PM

I love this tutorial and liked it the first time I ran across it last year even before I joined the forum. At the time, though, there was something niggling in the back of my mind that something was a little off, but I couldn't put my finger on what it was until now with the recent thread where you pointed to the tutorial once more as well as the C# Quirks thread.

The thing that was bothering me was:
public class ContactObj
{
    :
}
:
public class frmContact : Form
{
    :
        public ContactObj Contact
        {
            get
            {
                return myContactObj;
            }
            set
            {
                myContactObj = value;
                UpdateGUI();
            }
        }
    :
}



It was the set that was bugging me, because one could have code that written as:
var frm = new frmContact();
var contact = new Contact();
contact.First = "Kahless";
frm.Contact = contact; // Nice! We got to populate the form before display!
frm.ShowDialog();



If the user changes the first name to "Alexander" in the GUI, then after the dialog returns, contact.First == "Alexander" even if the user cancels out and the dialog (assuming the dialog has both OK and Cancel buttons.

In my mind, either the Contact class should be a struct (as opposed to a class), or the UpdateObj() call in the form should only be called when OK is pressed (as opposed to for every text change event).

Any which way, though, great tutorial!

This post has been edited by Skydiver: 01 June 2012 - 01:15 PM

Was This Post Helpful? 1
  • +
  • -

#17 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5595
  • View blog
  • Posts: 11,971
  • Joined: 02-June 10

Posted 01 June 2012 - 02:36 PM

structs are fairly out of date in todays C# coding. They hold no advantage over a class that I am aware of.


Quote

If the user changes the first name to "Alexander" in the GUI


'The GUI'... Which GUI? Your example describes a main form and an instance of the frmContact.

You are completely right that the Main form's contact collection should not be updated unless the user click's [OK] on the frmContact being used to update. But that is easily handled. Just give the update form a temporary copy of the contact in question. If they [OK] then update your live data. If they [CANCEL] then don't.

        private bool UpdateContact(ContactObj updateMeObj)
        {
            bool success = false;

            var updateForm = new frmContact { tempContact = (ContactObj)updateMeObj.Clone() };
            DialogResult dr = updateForm.ShowDialog();
            if (dr != DialogResult.OK) return false; // User canceled out don't update our data

            // At this point updateForm.tempContact still exists so we can use it to update our current data
            updateMeObj = (ContactObj)updateForm.tempContact.Clone(); // Only replace our data if the user hits OK
            return success; // The calling method can use this true to trigger an update of the database
        }

        #endregion
    }


    public class frmContact : Form
    {
        #region Fields

        public ContactObj tempContact;

        #endregion

        #region Methods

        public void Form_Shown(object sender, EventArgs e)
        {
            UpdateGUI();
        }

        private void UpdateGUI()
        {
            //TODO: Populate all the GUI controls
        }

        #endregion
    }

    public class ContactObj : ICloneable
    {
        #region ICloneable Members

        public object Clone()
        {
            var returnable = new ContactObj();
            //TODO: Finish the clone method
            return returnable;
        }

        #endregion
    }


Was This Post Helpful? 0
  • +
  • -

#18 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3631
  • View blog
  • Posts: 11,327
  • Joined: 05-May 12

Posted 01 June 2012 - 03:06 PM

View PosttlhIn`toq, on 01 June 2012 - 02:36 PM, said:

structs are fairly out of date in todays C# coding. They hold no advantage over a class that I am aware of.


They are value types rather than reference types. So as a value type, the assignment frmContact.Contact = contact; would have just copied the values over (eg. Clone()'d), and any changes done inside the form would not have affected the external contact instance.

View PosttlhIn`toq, on 01 June 2012 - 02:36 PM, said:

Quote

If the user changes the first name to "Alexander" in the GUI


'The GUI'... Which GUI? Your example describes a main form and an instance of the frmContact.

Sorry, by GUI, I meant the UI presented by frmContact when ShowDialog() is called.

Was This Post Helpful? 1
  • +
  • -

#19 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5595
  • View blog
  • Posts: 11,971
  • Joined: 02-June 10

Posted 01 June 2012 - 03:23 PM

I'm in the habit of everything being classes. No confusion. Everything in every app gets handled in the same way. Nobody on the team needs to be intimately aware with every type: IE

Quote

The widget is a class, the gadget is a struct, what type is the thingie again? <spend time looking it up>
Everything is an object. Everything therefore is a reference type. Everything has to be cloned. Everything has to be dealt with in the same way and obeys the same rules as everything else.

Therefore everything is inheritable. I can have

ContactClass
UserClass : ContactClass
ManagerClass : ContactClass
CustomerClass : ContactClass

So, to me, the value type v. reference type isn't something I would put in the "advantage" column.
Was This Post Helpful? 0
  • +
  • -

#20 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5595
  • View blog
  • Posts: 11,971
  • Joined: 02-June 10

Posted 16 September 2012 - 12:56 PM

It was pointed out to me that I hadn't shown how to deserialize.
This is covered on the MSDN, but its true I should have put it in the article.


            OpenFileDialog ofd = new OpenFileDialog();
            DialogResult dr = ofd.ShowDialog();
            if (dr != DialogResult.OK) return;


            var x = new System.Xml.Serialization.XmlSerializer(typeof(ContactObj));
            using (var sw = new StreamReader(ofd.FileName))
            {
                object o = x.Deserialize(sw);
                var newForm = new frmContact {Contact = (ContactObj) o};
                newForm.Show();
            }


Was This Post Helpful? 0
  • +
  • -

#21 Michael26  Icon User is offline

  • DIC-head, major DIC-head
  • member icon

Reputation: 362
  • View blog
  • Posts: 1,534
  • Joined: 08-April 09

Posted 16 September 2012 - 01:30 PM

is this your quirk(or should i say preference) , using
if (dr != DialogResult.OK) return;



instead of
if (dr == DialogResult.Cancel) return;


This post has been edited by Michael26: 16 September 2012 - 01:30 PM

Was This Post Helpful? 0
  • +
  • -

#22 tlhIn`toq  Icon User is offline

  • Please show what you have already tried when asking a question.
  • member icon

Reputation: 5595
  • View blog
  • Posts: 11,971
  • Joined: 02-June 10

Posted 16 September 2012 - 03:45 PM

I like to be very explicit. I only want to continue if every is OK. Rather than assume that the user found some way to return DialogResult.Yes for example.

They could also have found some way to slip in...

DialogResult.Abort
.No
.Ignore

So I prefer to say "If I don't see exactly what I want, then you're up to something"
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2