Click here to Skip to main content
15,892,768 members
Articles / Desktop Programming / Windows Forms

Evolving Windows Forms Event Handling With Loosely Coupled Methods

Rate me:
Please Sign up or sign in to vote.
4.65/5 (10 votes)
15 Jun 2011CPOL3 min read 31K   502   17  
Reduce the exposure of OwnerObject members or resources by interfacing methods to child or sibling objects.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace FormEventsTests
{
    public partial class FormSettings : Form
    {
        Action<object, EventArgs> changeTitleDelegate;
        Action<object, EventArgs> displayPropsDelegate;

        IList<Person> people;

        public FormSettings ( Action<object, EventArgs> ChangeTitleDelegate )
        {
            this.changeTitleDelegate = ChangeTitleDelegate;

            InitializeComponent ( );

            //  we only need 2 event subscription
            uxSetTitle.Click += new EventHandler ( uxSetTitle_Click );

            //  this form of event we won't need to unsubscribe
            uxCloseSettings.Click += delegate { this.Close ( ); };
        }

        //  evolve how we handle events
        /*  Use an interface to loosely couple to events
         * 
         *  Problem for developers, especially GUI devs, is to remember to
         *  unsubscribe from all events. Even passing a reference to the Owning
         *  object exposes more risks. Limit the risks involved by exposing 
         *  event handlers, or worse, the entire Owning object.
         *  
         *  By interfacing our events, we expose ONLY the Actions. This can 
         *  be thought of as a default action should a certain event occur. Each
         *  implementation would be fairly custom, but the pattern will be 
         *  recognizable. Loosely coupled events will also make it easier to avoid
         *  what I call, 'functionCreep(this)'.
         *  
         *  functionCreep(this) is when you pass an OwnerObject reference to a child
         *  or sibling class. What happens is you start executing functions intimate
         *  to the OwningObject. functionCreep(this) invites exposure of the 
         *  OwningObject's resources.
         *  
         */
        public FormSettings ( IEventPublisher EventOwner )
        {
            //  couple to events
            changeTitleDelegate = EventOwner.ChangeFormTitle;
            displayPropsDelegate = EventOwner.DisplayProperties;

            InitializeComponent ( );
            fillPersonSelector ( );

            uxSetTitle.Click += new EventHandler ( uxSetTitle_Click );
            uxCloseSettings.Click += delegate { this.Close ( ); };

            //  subscribe
            uxPersonSelector.SelectedValueChanged += 
                new EventHandler ( uxPersonSelector_SelectedValueChanged );
        }

        private void fillPersonSelector ( )
        {
            //  get some test data
            people = new List<Person> 
            {
                new Person("David", "Silver City", "TX"),
                new Person("James", "Houston", "TX"),
                new Person("Mandy", "Waco", "TX"),
                new Person("Steven", "Santa Fe", "NM"),
                new Person("Tina", "Edmond", "OK"),
                new Person("Karlena", "Misson", "KS")
            };

            uxPersonSelector.DisplayMember = "Name";
            uxPersonSelector.DataSource = people;
        }

        void uxSetTitle_Click ( object sender, EventArgs e )
        {
            //  pre-process if necessary

            //  invoke delegate
            this.changeTitleDelegate ( this, 
                new GenericEventArgs<string> ( uxFormTitle.Text ) );
        }

        void uxPersonSelector_SelectedValueChanged ( object sender, EventArgs e )
        {
            //  invoke delegate
            this.displayPropsDelegate ( this,
                new GenericEventArgs<Person> ( (Person)uxPersonSelector.SelectedValue ) );
        }
    }

    public class Person
    {
        public Person ( string Name, string City, string State )
        {
            this.City = City;
            this.Name = Name;
            this.State = State;
        }

        public string City { get; set; }
        public string Name { get; set; }
        public string State { get; set; }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Business Analyst
United States United States
Born and raised in Texas. I have been involved in programming since the early days of the Apple II - AppleSoft Basic and assembly were the two languages back then. Since then, I have watched technology evolve; I have watched the languages evolve. Over the last 5 years, I have been programming in .Net, specifically C#.

I am currently employed as a software engineer in San Diego, CA.

Comments and Discussions