2

I'm developing a MVVM WPF application with C# and .NET Framework 4.6.

I have this class:

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChangedEvent(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

I have implemented here INotifyPropertyChanged because I don't want to implement it in all of my ViewModel classes.

To use this class, I use inherit:

public class Presenter : ObservableObject
{
    private string _someText;

    public string SomeText
    {
        get { return _someText; }
        set
        {
            _someText = value;
            RaisePropertyChangedEvent("SomeText");
        }
    }
}

But, is there a way to use ObservableObject using object composition?

I understand object composition as instead of inherit, create a private object instance of ObservableObject in class Presenter.

I'm not sure if any ViewModel class should implement INotifyPropertyChanged.

UPDATE:
This is not a duplicate question. I'm asking if a ViewModel has always to implement INotifyPropertyChanged interface or instead, I can use Object composition. I have explained before. Please, read carefully my question.

VansFannel
  • 45,055
  • 107
  • 359
  • 626
  • I have used `ReSharper` in the past which was using annotations on objects to provide `INotifyPropertyChanged` functionality. However I wanted to use my own implementation, as the resharper not always would give me the option to use annotations, and it would come down to manipulation of the compiled assemblies and inserting the appropriate functions in the right place. – XAMlMAX Mar 01 '16 at 12:23
  • I have updated my question with more details. – VansFannel Mar 01 '16 at 12:26
  • 2
    Reason why your `VM` needs to implement the `INPC` is because the UI, when using `Binding`, will use that event to refresh the screen. If you don't use Binding and only code-behind then yes, your `VM` doesn't need the `INPC` implementation. – XAMlMAX Mar 01 '16 at 12:29
  • Possible duplicate of [In MVVM should the ViewModel or Model implement INotifyPropertyChanged?](http://stackoverflow.com/questions/772214/in-mvvm-should-the-viewmodel-or-model-implement-inotifypropertychanged) – Meirion Hughes Mar 01 '16 at 13:04
  • This is not a duplicate question I'm asking about inherit and object composition with an object that has implemented INotifyPropertyChanged interface and ViewModel classes. Please, read my question carefully. – VansFannel Mar 01 '16 at 13:10

2 Answers2

0

Well, ... ViewModels are best to be viewed as Composition, but the notification part should be an implementation of the Interface (or in your case inheritance). You have your DTOs and your ViewModels would be a composition of the DTOs, depending on the scenario.

This implementation of the same stuff can be tedious, but for WPF is still necessary. What you can do to simplify the process is to use Veawrs like Fody. It changes your observation of the ViewModel. All of the properties of the VM are by default observable properties, but you exclude the ones you do not want to, or you can define for one property to let the UI know that it should also update others.

It keeps the code very clean and simple. You will not need to implement the Interface, but it will be inherited in build time if you give the class the needed attribute.

user853710
  • 1,715
  • 1
  • 13
  • 27
0

If you want to improve the robustness by avoiding code duplication and using strings in code. Then you could use the following base class.

I don't know an approach with composition, but this one is the best I know. Since it has some additional benefits (Cloning made easy a.s.o.)

public abstract class BindingBase : INotifyPropertyChanged
{
    private IDictionary<string, object> _backingFields;
    private IDictionary<string, object> BackingFields
    {
        get { return _backingFields ?? (_backingFields = new Dictionary<string, object>(); }
    }    
protected T GetValue<T>(Expression<Func<T>gt; expr) { var name = GetName(expr); return BackingFields.Contains(name) ? (T)BackingFields[name].Value : default(T); }
protected void SetValue<T>(Expression<Func<T>gt; expr, T value) { var name = GetName(expr); if (BackingFields.Contains(name) && BackingFields[name].Value.Equals(value)) return; // return without doing anything, since the value is not changing
BackingFields[name] = value; RaisePropertyChanged(name); }
private void RaisePropertyChanged(string name) { // you know this part
}
private string GetName (Expression<Func<T> expr) { // implementation can be found via google } }
Usage is quite easy.
public class BindingChild : BindingBase
{
    public string SampleProperty
    {
        get { return GetValue(() => SampleProperty); }
        set { SetValue(() => SampleProperty, value); }
    }
}

DHN
  • 4,807
  • 3
  • 31
  • 45