samedi 5 janvier 2019

How to design view model for generic model classes in C#?

I have a model class, let's say Data, which represents a database record. For Data, I have a view model class DataViewModel which wraps a Data object and exposes Data's properties.

Now, I have another model class Entry, which represents (and wraps) an entry of a database record in certain lists, while having its own set of properties. Therefore, the entry is a generic class Entry<T> and has a property EntryObject of type T. Simply put, an object of type Entry<Data> represents an entry of a Data object, and its property EntryObject is of type Data. I would like to have a view model of Entry<T> such that I do not have to expose Data to the view.

public class Data
{
    // Data Properties
}

public class Entry<T>
{
    // Entry Properties

    public T EntryObject { get; set; }
}

What I am confused about is the EntryObject property of Entry<T>. I have tried a view model which wraps a Entry<T> object, and has a property EntryObject which is also a view model. I used EntryViewModel<T> where T is the view model of a database record's model object. So, a view model of Entry<Data> will be of type EntryViewModel<DataViewModel>. However, since model class Entry<T> is also wrapped inside the view model, its type parameter is also required. For this, I used EntryViewModel<TViewModel, TModel>. Now, the view model of Entry<T> will of type EntryViewModel<DataViewModel, Data>.

public class DataViewModel : INotifyPropertyChanged
{
    private Data _Model;
    public Data Model {...}

    // Properties of Model
}

public class EntryViewModel<TViewModel, TModel> : INotifyPropertyChanged
{
    private Entry<TModel> _Model;
    public Entry<TModel> Model {...}

    public TViewModel EntryObject { get; set; }

    // Properties of Model
}

This works perfectly since I can make an object of type DataViewModel inside a view which refers to the EntryViewModel<DataViewModel, Data>'s EntryObject property.

public DataViewModel DataViewModelObject => EntryViewModelObject.EntryObject;

But because Data is hidden from the view, I cannot have an object of type EntryViewModel<DataViewModel, Data> inside a view, which is needed since Entry<T> has its own properties as well. I can have each property of Entry<T> (exposed via its view model) available inside the view as the view's properties, like

public int EntryProperty1 => EntryViewModelObject.EntryProperty1;

but that would produce a lot of duplicate code since each property will be declared as the property of every view which displays a Entry<T> object.

Is there a way to avoid passing TModel into EntryViewModel while retaining the EntryObject? Thanks.

Aucun commentaire:

Enregistrer un commentaire