I have two screens:

  • A screen with a list of items, where every item in the list has "Show Details" and "Update buttons"
  • An item details screen. The "Show Details" button navigates to item details screen.

When clicking the "Update" button, it needs to take a decision based on item state and then navigate to either to item update screen or ask user for some confirmation before proceeding.

The item details screen has same "Update" button which has same logic.

enter image description here

The issue I have is how to implement the view-models in a clean way such that the update logic is not duplicated.

First, I created the view-models for the screens:

class ItemListViewModel
{
    public ObservableCollection<ItemViewModel> Items { get; }
}

class ItemDetailsViewModel
{
    // How does this calls ItemViewModel:UpdateCommand ?
    public ICommand UpdateCommand { get; }
}

class ItemViewModel 
{
    public ICommand ShowDetailsCommand { get; }
    public ICommand UpdateCommand { get; }
}

For sharing the UpdateCommand, I see the following options:

  1. Have ItemDetailsViewModel create and keep an instance of ItemViewModel:

    class ItemDetailsViewModel
    {
        ItemViewModel _itemViewModel;
       public ICommand UpdateCommand => _itemViewModel.UpdateCommand;
    }
    
  2. Have ItemDetailsViewModel derive from ItemViewModel:

    class ItemDetailsViewModel : ItemViewModel
    {
    }
    
  3. Use a service which implements the update logic, and have both ItemViewModel and ItemDetailsViewModel call it

    interface IItemService
    {
       void Update();
    }
    

Note that part of the update logic is navigation. I have an IINavigationService which is injected in view-models. I'd have to pass it to the IItemService if I choose to use it.

I don't know which one is the best and why. Here's some of the concerns I have:

  • Option #2: seems weird to derive from ItemViewModel.
  • Options #3: using the IItemsService service seems appealing, but how to differentiate this service from another items service which is actually saving to storage? Just look at the service and its "Update" method you'd not think it just for navigation logic.

I'd appreciate some advice and reasoning.

The articles\books I could find on MVVM are too simple and don't talk about more complicated scenarios.

  • Id go with the service as it allows the use of detail or other views without depending on your list – Ewan Aug 11 at 8:04
  • @Ewan Thanks. I have some concerns about that. Could you please look at my update? – Daniel Aug 11 at 8:18
up vote 2 down vote accepted

I would stick with third option.

The first one is not obvious and smells (imho), coupling is always bad. More than that, what happens if you decide to remove the button from "inner" class? It will break the "outer" one. Coupling should be avoided.

The second one is weird, inheritance should be used to extend some functionality, not to share some code. You have two completely different screens so they dont have parent-child relationship. And again, what if you decide to remove functionality from parent class and keep it in child? You, most likely, will move your implementation to child class, but at that point inheritance would make absolutely no sense at all. If you really like the inheritance idea I recommend you at least create third class, that will be inherited by yours two.

The only issue with third option, as you said, is naming. But this is always an issue. I suggest using name like "ItemUpdateButtonProcessor", this way you won't confuse it with update action itself (imho). I am not familiar with the language you use, so maybe there're some best practices on the topic, but I think you get the idea.

  • 2
    Thanks. I upvoted your comment but someone else downvoted it, I wish I knew why. I hate voting without giving any reason for it. I just don't understand why you would care enough to vote but not want to spend 15 secs writing few words.... Doesn't make any sense – Daniel Aug 11 at 12:35
  • I don't really care about my rating:) This is a question-answer site and it is intended to help people. If you find my answer helpful that is good enough for me:) Good luck – Nondv Aug 11 at 12:55

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.