0

I'm new to the MVVM pattern and I have an assignment to implement a TreeView which acts like a work space viewer (sort of like eclipse's/vs's solution explorer). The tree view can contain multiple types of items (like a file, a folder of other items etc). I have created the Models (the Folder's model have Children (which can be any kind of item), Name etc).

Example model:

public class SystemFolder: IWorkspaceItem
{
    string mTitle;

    public ObservableCollection<IWorkspaceItem> Children { get; set; }

    public string Path
    {
        get { return mTitle; }
        set
        {
            mTitle = value;
            OnPropertyChanged("Title");
        }
    }

    //Constructor
    public SystemFolder(string name, ItemType type, string path)
        : base(name, type)
    {
        Path = path;
        Children = new ObservableCollection<IWorkspaceItem>();

        //add children here...
    }
    //Some more code here..
}

I've created a ViewModel for each model (Which all store the model's instance). The ViewModels have the necessary properties that the view needs (like Title, Children etc).

Example ViewModel:

public class SystemFolderViewModel : TreeViewModelItem
{
    SystemFolder mFolder;
    ObservableCollection<TreeViewModelItem> mChildren;
    public ObservableCollection<TreeViewModelItem> Children
    {
        get { return mChildren; }
    }

    //====================
    // Constructor
    //====================
    public SystemFolderViewModel(SystemFolder folder, TreeViewModelItem parentWorkspaceItem)
        : base(parentWorkspaceItem)
    {
        mFolder = folder;

        mFolder.Attach(OnItemPropertyChanged);
    }

    public string Name
    {
        get { return mFolder.Name; }
        set { Name = value; }
    }

    public string IconPath
    {
        get { return mFolder.ItemType.IconPath; }
        set { IconPath = value; }
    }
    //Some more code here..
}

I've also implemented the View which defined the HierarchicalDataTemplate of each ViewModel. It all works fine and I actually made a mockup.

Example of HierarchicalDataTemplate in View:

<HierarchicalDataTemplate
    DataType="{x:Type local:SystemFolderViewModel}"
    ItemsSource="{Binding Children}">
            <StackPanel Orientation="Horizontal">
            <Image Width="16" Height="16" Margin="3,0" Source="{Binding Path=IconPath}"/>
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
</HierarchicalDataTemplate>

The whole initialization:

Workspace data_model = new Workspace("Main Workspace", PredefinedTypes.GetWorkspaceType(), Database.GetItems());
        TreeViewModel vm = new TreeViewModel(data_model);
        WorkspaceView viewer = new WorkspaceView(vm);
//add to grid etc..

Now my problem is that my program is dynamic. Meaning, items can be added to the TreeView in run-time. Now let me explain how I understand MVVM should work and please correct me. The Data model provides the view with items. So my program should only add items to the data model. The main ViewModel of the tree holds a DataModel instance which hold the workspace's main children.

Each item that is added to the model should automatically update the ViewModel which in turn should update the view. Since I only update the DataModel, when I add a child to one of its items, the ViewModel should find the corresponding item in the ViewModel and add a new child to it. Why do I have to have two seperate collections? The DataModel's Children and the ViewModel Children.

I need every data model to inherit from INotifyPropertyChanged so it will update its ViewModel. Also as I said, there are data models which have their own children. If that collection changes I need the collection in the item's ViewModel to change. This all seems kind of dumb to me. Why should I get through all this trouble? Why can't I just add items to the ViewModel which will update the view? What am I missing? How do I need to go about with this?

If you need more info, please ask me and I will provide/explain.

Thank you! Dolev.

dlvhdr
  • 482
  • 4
  • 19
  • Have you tried Google? Josh Smith's article would have been one of your first hits: http://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode – EagleBeak May 19 '14 at 14:56
  • 1
    I think, dlv's question is about, why he needs both data model and view model in his case. It is not simply about how to implement the tree view with MVVM, which is described in the referenced article. This thread might be related and useful: http://stackoverflow.com/questions/5027562/the-role-of-the-model-in-mvvm – Edin May 19 '14 at 15:05
  • 1
    @div, in the case you described, you probably can get by with updating the vm directly - OR by having the vm poll the data periodically. – Gayot Fow May 19 '14 at 15:44
  • Thank you all, you've been very helpful. I did read the codeproject example and a lot of my TreeView code is based on that example. @Edin From what I read in the link you gave, I should give up the model classes and just update the vm directly. I might do that. But let's say I continue with this method: When an item in the work space is updated I need to look for it in the ViewModel. How do I look for it? I need to catch every add/remove/update event that happens in the model and find the appropriate item in the ViewModel. Can you help me with that? – dlvhdr May 19 '14 at 18:36
  • 1
    Your question is about matching an item from Model to the corresponding ViewModel item. How you do that depends from multiple factors: does your model item have a unique Id? Does the model item object reference change during the application lifecycle? do you pass your model to the view model? etc... you may find the following thread also useful: http://stackoverflow.com/questions/10324009/mvvm-modified-model-how-to-correctly-update-viewmodel-and-view – Edin May 20 '14 at 08:09
  • By the way: Change `OnPropertyChanged("Title");` to `OnPropertyChanged("Path");` – Alex F May 21 '14 at 15:30

0 Answers0