Further to my previous post, Erik Meijer commented that an overload to the FromEvent method is available to convert from generic event handlers to the specific ones used by much of the BCL. So the code from the previous post would look something like this now:

        #region Ctor
        public MainPage()
        {
            InitializeComponent();

            var mouseEventSource = Observable.FromEvent<MouseEventHandler, MouseEventArgs>(
                eh => new MouseEventHandler(eh),    // Conversion
                eh => this.MouseMove += eh,         // Subscribe
                eh => this.MouseMove -= eh);        // Unsubscribe

            _mouseMoveSubscription = mouseEventSource.Subscribe(OnMouseMove);
        }
        #endregion

        private void OnMouseMove(Event<MouseEventArgs> e)
        {
            var position = e.EventArgs.GetPosition(this);

            Debug.WriteLine("Mouse moved.  Position: {0}.", position);
        }

This solves one of my major gripes. Exciting times!

Advertisements

I just wrote a base class that I’m going to derive all of my notifying Domain Models from. It solves the horror of passing around the property name of a changing property in the INotifyPropertyChanged implementation. This has the enormous benefit of being able to check your Property Names at compile-time and also allows you to keep everything in sync when using tools like Resharper (if you don’t use Resharper – then you really should!) to rename things. It uses lambda expressions to specify the Property that’s changing.

    public abstract class ModelBase<T> : INotifyPropertyChanged where T : ModelBase<T>
    {
        #region Events
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region Public Methods
        public static string GetPropertyName<R>(Expression<Func<T, R>> expression)
        {
            var memberExpression = expression.Body as MemberExpression;
            if (memberExpression == null)
            {
                throw new ArgumentException("'expression' should be a member expression");
            }
            var propertyName = memberExpression.Member.Name;
            return propertyName;
        }
        #endregion

        #region Protected Methods
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
        protected void RaisePropertyChanged<R>(Expression<Func<T, R>> expression)
        {
            var propertyName = GetPropertyName(expression);
            this.OnPropertyChanged(propertyName);
        }
        #endregion
}