Making the BindbleBase even more simple.

Mar 10, 2014 at 8:22 PM
I really like the new new BindableBase class over it's predecessor(NotificationObject).
It really makes big models easier to read after the logic for the propertySetter was moved to its baseclass.

But the BindableBase still needs the private fields hanging around in the model.
With the new [CallerMemberName] attribute, the base class can do this for us.
Moving this to the baseclass will make the Model class even more simple, and easier to maintain, and you can't really go wrong when you rename properties.

I want to go from this:
public class MyModel : BindableBase
    {
        private string _myString;
        public string MyString { get { return _myString; } set { SetProperty(ref _myString, value); } }

        private string _myString2;
        public string MyString2 { get { return _myString2; } set { SetProperty(ref _myString2, value); } }

        private double _myDouble;
        public double MyDouble { get { return _myDouble; } set { SetProperty(ref _myDouble, value); } }

        private int? _myInt;
        public int? MyInt { get { return _myInt; } set { SetProperty(ref _myInt, value); } }

        private object _myObject;
        public object MyObject { get { return _myObject; } set { SetProperty(ref _myObject, value); } }

        private MyEnum _myEnum;
        public MyEnum MyEnum { get { return _myEnum; } set { SetProperty(ref _myEnum, value); } }
    }
To this:
public class MySimpleModel : SimpleBindableBase
    {
        public string MyString { get { return Get<string>(); } set { Set(value); } }
        public string MyString2 { get { return Get<string>(); } set { Set(value); } }
        public double MyDouble { get { return Get<double>(); } set { Set(value); } }
        public int? MyInt { get { return Get<int?>(); } set { Set(value); } }
        public object MyObject { get { return Get<object>(); } set { Set(value); } }
        public MyEnum MyEnum { get { return Get<MyEnum>(); } set { Set(value); } }
    }
Here is a working example of the SimpleBindableBase that extends the BindableBase class.
 public class SimpleBindableBase : BindableBase
    {
        private readonly Dictionary<string, object> _fields = new Dictionary<string, object>();

        protected virtual void Set<T>(T value, [CallerMemberName] string propertyName = null)
        {
            if (propertyName == null) throw new ArgumentNullException("propertyName");
            if (_fields.ContainsKey(propertyName))
            {
                var oldValue = _fields[propertyName];
                if (Equals(oldValue, value)) return;

                _fields[propertyName] = value;
                this.OnPropertyChanged(propertyName);
            }
            else
            {
                if (Equals(value, default(T))) return;
                _fields.Add(propertyName, value);
                this.OnPropertyChanged(propertyName);
            }
        }

        protected virtual T Get<T>([CallerMemberName] string propertyName = null)
        {
            if (propertyName == null) throw new ArgumentNullException("propertyName");
            if (!_fields.ContainsKey(propertyName)) return default(T);
            return (T)_fields[propertyName];
        }
    }
Any thoughts on this?
Mar 11, 2014 at 5:46 PM
Hi,

Thanks for sharing your solution with the community. It would be helpful if you could also post it as a work item so that it could be considered as a suggestion for future releases.

Regards.

Gabriel Ostrowsky.
https://blogs.southworks.net/gostrowsky
Marked as answer by Mcpd_Thomas on 3/11/2014 at 1:03 PM
Mar 11, 2014 at 8:02 PM
Hi,

Thanks for you reply.
I have posted this as "Suggestion for BindableBase" in the Issue section.
Jul 8, 2014 at 12:43 PM
It's an interesting idea, but I prefer the strongly typed values over the easier coding. With your solution there would be a lot of boxing between object and type all the time. Do you see this as a concern? I wonder about the Equality check for example, Equals(object, type).

My preference in the Set property method for comparison is the following:
        if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
My ViewModels usually have a lot more code in them than just the properties and therefore not sure if I would gain a lot. CSLA uses a similar concept for property storage that is then utilized by other features like business rules, validation, serialization, and the sorts, but it made the components responsible for too much making them harder to code and read in the long run. I no longer use that framework.