开发者

Does the ViewModel hold the model?

At the moment I have the following structure of my application:

  • A folder named ViewModels
  • A folder called Views
  • A folder called Services

The ViewModel has a class, called ItemTypeDetailViewModel. How it looks:

public class ItemTypeDetailViewModel
{
    private IItemTypenService itemTypeService;
    public ObservableCollection<Models.ItemType> ItemTypes { get; set; }
    public ICollectionView CollectionView { get; set; }

    public ItemTypeDetailViewModel()
    {
        itemTypeService = new ItemTypeService();
        itemTypeService.GetItemTypes();

        CollectionView = CollectionViewSource.GetDefaultView(ItemTypes);
    }
}

In the class I have a reference to the Service Layer (for now no DI, just newing in the constructor). With the help of the itemTypeService I will get a collection of ItemTypes. This is maybe a more MVP kind of structuring?

But now I start to get confused because most of the examples I see of MVVM have the model wrapped in a ViewModel.

What is a good approac开发者_StackOverflow社区h here?


But now I start to get confused because most of the examples I see of MVVM have the model wrapped in a ViewModel.

What is a good approach here?

If each of your data items (a Model) is trivial, and the way you are using them in the View is also trivial, then there's no problem at all with exposing them "as is" from the ViewModel (creating extra work just because is never a good idea). On the other hand, if you find you need functionality that is not extremely easy to achieve it might be an indication that you need to wrap each Model in its own ViewModel (an ItemTypeViewModel).

An example of when you may not need a ViewModel is displaying the items in a read-only list, in which case you will be good to go with a DataTemplate and nothing more. The counter-example would be if you need to edit them and the edits need to be validated; the ViewModel will then hold the validation logic.

To sum it up: don't go berserk with MVVM if there's no reason to. Be practical.

A final note regarding the ViewModel having access to the View:

There is no problem in doing that as long as you do not use public interface of the view's runtime type. In fact, ViewModel-first MVVM requires that the ViewModel have a reference to the View. Many people will tell you that this is an automatic mistake -- they are wrong, and probably influenced by the fact that View-first (which is the MVVM flavor found in most examples) doesn't have the ViewModel reference the View.

If it is OK for the View to have a reference to the ViewModel as its DataContext, then it's also OK for the converse to happen. The important point is how that reference is used: public object View { get; set; } is certainly fine because it does not introduce any coupling; but public MyUserControl View { get; set; } is not, because it couples the ViewModel to the specific type MyUserControl.


(First part from my comment above: The View should bind to a ViewModel. The ViewModel cannot know anything about potential views. You might write a new view to work with an existing ViewModel - or you might write unit tests for your ViewModel and so a view referred to in the ViewModel is inappropriate.)

I'm not sure exactly what you're trying to do but this looks like the detail view for an ItemType. I can't see why then you'd have ALL item types queried within the constructor?

I would do something like this:

  • Create an ItemTypesViewModel, which has a collection of ItemTypeDetailViewModel, lazy-loaded
  • Create a repository somewhere that the ViewModels use to query the model (data) (e.g. the IItemTypeService does this I imagine)

A quick example, without the lazy-loading:

    public class ItemTypesViewModel : ViewModelBase
    {
        private List<ItemTypeDetailViewModel> itemTypeViewModels;

        public IEnumerable<ItemTypeDetailViewModel> ItemTypes
        {
            get
            {
                return itemTypeViewModels;
            }
        }

        public ItemTypesViewModel(IItemTypeService service)
        {
            // populate itemTypeViewModels using service here
        }
    }

Update, more relevant I think/hope: What I usually do in terms of accessing the service layer is have a static member in the ViewModel class that acts as a factory memory. Example:

public class ItemTypesViewModel : ViewModelBase
{
    public static ItemTypesViewModel Create(IItemTypeService service)
    {
        // build and return object here
    }
}

At some point you've got to cross the boundaries, and this method is to my personal taste.. would be interested to see what others do. Perhaps an additional layer or set of factories for ViewModels. ?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜