Ask a questionAsk a question
 

AnswerRequesting a specific ViewModel from the View?

  • Wednesday, November 04, 2009 5:52 PMsaxisa Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I am working on the architecture for a custom user control.  Basically, it has a very specific and custom layout, and I need to place specific elements in specific locations.  The elements themselves are ViewModels pulling data from a model.

    So for example, if I have a ObservableCollection of SubViewModel elements, each with an ID field, that are within a MainViewModel.  From the MainView, because of this custom layout, the SubViewModel with ID=1 has to go in position 1 (wherever that may be), the SubViewModel ID=2 goes somewhere else etc.

    I cant just assign a DataContext here(?) because of the custom layout, but I also dont know how to do something like:

    <viewmodel:SubViewModel Grid.Column=2 ID="1" />

    And have the right SubViewModel retrieved and displayed.

    What is the right way to do this?  Is there a way for the view, in XAML to request a specific element from the viewmodel?

    Or am I just totally confused, and on the wrong track?  (certainly possible!)  


Answers

  • Wednesday, November 04, 2009 6:20 PMHomeroThompson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hello,

    Have an observable collection of viewmodels (SubViewModels here) is a good approach. If you want to list and show the detail of each SubViewModel you need an items control (a control that can show multiple items) and create a data template for the subitem. For example:

    <ItemsControl ItemsSource="{Binding SubViewModelList}">
        <ItemsControl.ItemTemplate>   
            <DataTemplate>
                    <!-- Your data template  to show SubViewModels -->
            </DataTemplate>
        </ItemsControl.ItemTemplate>   
    </ItemsControl>

    Good Luck.
    • Marked As Answer bysaxisa Wednesday, November 04, 2009 9:22 PM
    •  
  • Wednesday, November 04, 2009 7:25 PMdmikon Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Personally, I would use the following approach:

    Each section of your main view would be its own control and have its own ViewModel. The controls would not know anything about each other and the view would be free to arrange them in any way it wanted to. The communication between the ViewModels would be handled by a Mediator (here's an example/brief overview: http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/ ). Your main view, in this scenario, would act more like a shell that simply encapsulates the different pieces of your app.
    • Marked As Answer bysaxisa Wednesday, November 04, 2009 9:22 PM
    •  
  • Wednesday, November 04, 2009 7:42 PMReed Copsey, Jr. Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    In this case, using your 4 section examples, the SubViewModel for position 1 will -always- be ID=1.  Some other data elements may change in the model and get displayed in a 'SubElement' view, but thats all that would change.

    It sounds like I was headed in the right direction with the controlling viewmodel, but Im not sure how to use DataTemplates to pull specific SubViewModels out of the main ViewModel for each position?
    If your properties on the ViewModel are just setup like:

    public object Position1Object { get; set; } // +Implement INotifyPropertyChanged, alternatively, use a base class for your VM here instead of object

    Then the MainViewModel can set ANY object (ViewModel) into that position.  The view would just have a content presenter for each position, and the ViewModel can place any control into positions 1-4 at will.  This gives you complete control over how things are rendered in the view side, and the actual content used on the ViewModel side, with no coupling between the two.

    The DataTemplates can match ViewModel->View for you.
    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked As Answer bysaxisa Wednesday, November 04, 2009 9:22 PM
    •  

All Replies

  • Wednesday, November 04, 2009 6:15 PMReed Copsey, Jr. Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I normally handle this by having a "controlling" viewmodel.  For example, say your view will have 4 sections (position 1 - 4).  If the content within those is changing at runtime, the ViewModel can be used to coordinate this.  It just needs 4 properties, one for the object (ViewModel) that goes into each position.

    The view can then just setup 4 separate content presenters, each bound to the relevant property in the ViewModel.  If there is a data template setup to map each potential ViewModel -> View, it's just a matter of having the main VM set ViewModels to the 4 properties when it wants to change things around, and the Views automatically keep in sync. 
    Reed Copsey, Jr. - http://reedcopsey.com
  • Wednesday, November 04, 2009 6:20 PMHomeroThompson Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Hello,

    Have an observable collection of viewmodels (SubViewModels here) is a good approach. If you want to list and show the detail of each SubViewModel you need an items control (a control that can show multiple items) and create a data template for the subitem. For example:

    <ItemsControl ItemsSource="{Binding SubViewModelList}">
        <ItemsControl.ItemTemplate>   
            <DataTemplate>
                    <!-- Your data template  to show SubViewModels -->
            </DataTemplate>
        </ItemsControl.ItemTemplate>   
    </ItemsControl>

    Good Luck.
    • Marked As Answer bysaxisa Wednesday, November 04, 2009 9:22 PM
    •  
  • Wednesday, November 04, 2009 6:33 PMsaxisa Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I normally handle this by having a "controlling" viewmodel.  For example, say your view will have 4 sections (position 1 - 4).  If the content within those is changing at runtime, the ViewModel can be used to coordinate this.  It just needs 4 properties, one for the object (ViewModel) that goes into each position.

    The view can then just setup 4 separate content presenters, each bound to the relevant property in the ViewModel.  If there is a data template setup to map each potential ViewModel -> View, it's just a matter of having the main VM set ViewModels to the 4 properties when it wants to change things around, and the Views automatically keep in sync. 
    Reed Copsey, Jr. - http://reedcopsey.com
    In this case, using your 4 section examples, the SubViewModel for position 1 will -always- be ID=1.  Some other data elements may change in the model and get displayed in a 'SubElement' view, but thats all that would change.

    It sounds like I was headed in the right direction with the controlling viewmodel, but Im not sure how to use DataTemplates to pull specific SubViewModels out of the main ViewModel for each position?
  • Wednesday, November 04, 2009 6:36 PMsaxisa Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    Thanks Homero, seems like that is headed in the right direction too.  Im not sure how I would do the DataTemplate part though, since I need to put SubViewModel ID=1 in one spot, ID=2 in another fixed (and custom) position in the layout.


  • Wednesday, November 04, 2009 7:25 PMdmikon Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Personally, I would use the following approach:

    Each section of your main view would be its own control and have its own ViewModel. The controls would not know anything about each other and the view would be free to arrange them in any way it wanted to. The communication between the ViewModels would be handled by a Mediator (here's an example/brief overview: http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/ ). Your main view, in this scenario, would act more like a shell that simply encapsulates the different pieces of your app.
    • Marked As Answer bysaxisa Wednesday, November 04, 2009 9:22 PM
    •  
  • Wednesday, November 04, 2009 7:42 PMReed Copsey, Jr. Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    In this case, using your 4 section examples, the SubViewModel for position 1 will -always- be ID=1.  Some other data elements may change in the model and get displayed in a 'SubElement' view, but thats all that would change.

    It sounds like I was headed in the right direction with the controlling viewmodel, but Im not sure how to use DataTemplates to pull specific SubViewModels out of the main ViewModel for each position?
    If your properties on the ViewModel are just setup like:

    public object Position1Object { get; set; } // +Implement INotifyPropertyChanged, alternatively, use a base class for your VM here instead of object

    Then the MainViewModel can set ANY object (ViewModel) into that position.  The view would just have a content presenter for each position, and the ViewModel can place any control into positions 1-4 at will.  This gives you complete control over how things are rendered in the view side, and the actual content used on the ViewModel side, with no coupling between the two.

    The DataTemplates can match ViewModel->View for you.
    Reed Copsey, Jr. - http://reedcopsey.com
    • Marked As Answer bysaxisa Wednesday, November 04, 2009 9:22 PM
    •  
  • Wednesday, November 04, 2009 9:22 PMsaxisa Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I like that, makes sense to me.  Thanks all for the excellent replies!