Where to put the association model -> view model?

67 views Asked by At

I have basically the following code to implement my flavour of MVVM:

public class ElementA : IElement
{}

public class ElementB : IElement
{ }

public class VMElementA : IElementViewModel // for element A
{ }
public class VMElementA2 : IElementViewModel // another option vor element A
{ }
public class VMElementB : IElementViewModel // for element B
{ }


public class ContainerModel
{
    public IElement[] Elements { get; }
    public void AddNewElement(IElement element);
}

public class ContainerVieWModel
{
    private ContainerModel model;

    public IElementViewModel[] Elememnts
    {
        get
        {
            return model.Elements.Select(e => ?).ToArray();

        }
    }

    // is called internally, e.g. activated by a command
    private void AddNewElement(? element)
    {
        model.AddNewElement(?);
    }
}

I have a model containing a list of IElements, which are accessed by the view model. The view model needs to provide the corresponding view models.

I want to achieve this under the following restrictions:

  1. I don't want the model (e.g. ElementA or ContainerModel) to "know" it's view model. Some models may even have more than one possible view model, so it couldn't be hardcoded.

  2. I'd like the element creation to take place in the model code, not the view model code.

Things I've considered so far:

  • Things I've done in similar cases (without creation) was to add wrapper elements to the model, containg the element and a delegate capable of turning the model into a view model.

    public interface IExtendedElement
    {
        IElement Model { get; }
        IElementViewModel GetViewModel(); //possibly other arguments
    }
    
    public class ExtendedElement<T> : IExtendedElement where T : IElement
    {
        private readonly T model;
        private readonly Func<T,  IElementViewModel> viewModelGenerator;
    
        public ExtendedElement(T model, Func<T,  IElementViewModel> viewModelGenerator)
        {
            this.model = model;
            this.viewModelGenerator = viewModelGenerator;
        }
    
    
        public IElement Model
        {
            get { return model; }
        }
    
        public IElementViewModel GetViewModel()
        {
            return viewModelGenerator(model);
        }
    }
    
  • Another way would be to store the mapping functions and perform the mapping model -> view model in the view model using the collection of functions. This could produce some runtime errors if there is no function capable of mapping a certain model.

    public partial class ContainerViewModel
    {
        // the conversion functions have to case the element to the appropriate "real" type
        private IDictionary<Type, Func<IElement, IElementViewModel>> modelToViewModel;
        public IElementViewModel[] Elememnts
        {
            get
            {
                return model.Elements.Select(e => Map(e)).ToArray();
    
            }
        }
    
        private IElementViewModel Map(IElement element)
        {
            // how can I assure that the conversion function is present?
            return modelToViewModel[element.GetType()](element);
        }
    
    }
    

Both approaches don't seem right to me. Any advice will be appreciated.

0

There are 0 answers