none
MVVM Bind View to ViewModel via XAML

    Question

  • Hi,

    I faced with problem that I can't bind View to ViewModel without using code behind file.

    Generally I use the following code to bind my ViewModel to the View, in resource dictionary:

    Resource Dictionary:

     <DataTemplate DataType="{x:Type ViewModels:MyViewModel}">
     <View:MyView/>
     </DataTemplate>
    

     

    My View:

    <UserControl>
    
     <UserControl.Resources>
     <ResourceDictionary Source = "ConfigurationViewsResources.xaml"/>
     </UserControl.Resources>
     
     <Grid>
    <!--Content Here-->
    </Grid>
    </UserControl>
    

     

    well, it doesn't work !

    Why ? what I'm doing wrong ?

     Thank u in advance,

    Julian

    Tuesday, November 09, 2010 11:20 AM

Answers

  • There are lots of ways to do this, but here's the easiest for basic cases:

     

     

    <Window>
     <Window.Resources>
      <local:MainViewModel x:Key="ViewModel"/>
     </Window.Resources>
    
     <Grid>
      <local:MyView DataContext="{Binding Source={StaticResource ViewModel}}"/>
     </Grid>
    </Window>
    

     

     

    This does not support constructor arguments for the ViewModel, however.

    Tuesday, November 09, 2010 4:28 PM

All replies

  • As far as I understand, the code above is the same thing: MyView.DataContext = new MyViewMode();

    is it correct or not ?

     

    Tuesday, November 09, 2010 11:36 AM
  • Hi, using DataTemplate and its DataType property is not actually binding a view-model to your view. It just says that when it encounters this view-model object, use the following view as its template. Let's say your XAML has a ContentControl like this: <ContentControl Content="{Binding MyViewModel}"/> WPF looks at the MyViewModel and search for the corresponding template. When it finds your DataTemplate, it sets the Content to MyView and its DataContext to MyViewModel automatically. So what's probably missing in your code is where you bind MyViewModel.
    Tuesday, November 09, 2010 12:36 PM
  • As far as I understand, the code above is the same thing: MyView.DataContext = new MyViewMode();

    is it correct or not ?

     


    This is NOT correct. When you set the DataContext property , we can binding to the data object property in View directly. But in your first post, you defined one DataTemplate. Generally, we use the DataTemplate to control how the data object (here is your ViewModal) be displayed (with controls and layout).

    Please check here for more info. http://msdn.microsoft.com/en-us/library/ms742521.aspx (Data Templating Overview )

     

    Hope this helps.


    Keep improving.
    Yiling Lai. MVP (Visual C++ and Client App Dev)
    Tuesday, November 09, 2010 12:40 PM
  • Thank you for your replay.

    Could you please show me little example, where you bind ViewModel.

     

    Will be appreciated for any line of code :)

     

    Julian

     

    Tuesday, November 09, 2010 1:39 PM
  • Hello, If you are like to use MVVM, just use the DataContext binding you have done, it is the suitable method for MVVM to set the binding source.


    Keep improving.
    Yiling Lai. MVP (Visual C++ and Client App Dev)
    Tuesday, November 09, 2010 4:02 PM
  • Hi Yiling Lai,

    You are right, it works for me. But the thing is, that I want to delete each codebehind file for each view. You could ask me why ? It's just to prevent the possibility of writing code in codebehind.

    regards,

    J.

    Tuesday, November 09, 2010 4:08 PM
  • For that purpose, I'd like to know how to implement such things, when I have two or more views.
    Tuesday, November 09, 2010 4:18 PM
  • There are lots of ways to do this, but here's the easiest for basic cases:

     

     

    <Window>
     <Window.Resources>
      <local:MainViewModel x:Key="ViewModel"/>
     </Window.Resources>
    
     <Grid>
      <local:MyView DataContext="{Binding Source={StaticResource ViewModel}}"/>
     </Grid>
    </Window>
    

     

     

    This does not support constructor arguments for the ViewModel, however.

    Tuesday, November 09, 2010 4:28 PM
  • thanks Ben !
    Tuesday, November 09, 2010 4:53 PM
  • Just another question regarding current topic.

    Can I do the following things. Let say, that I have  2 ViewModels, MyViewModel1 and MyViewModel2.

    So, in resource dictionary I have:

     

      <DataTemplate DataType="{x:Type ViewModels:MyViewModel}">
        <View:MyView/>
      </DataTemplate>
    
      <DataTemplate DataType="{x:Type ViewModels:MyViewModel2}">
        <View:MyView2/>
      </DataTemplate>
    

    and on my MainView I do the following:

     

          ObservableCollection<object> viewModels = new ObservableCollection<object>();
    
          viewModels.Add(new MyViewModel());
          viewModels.Add(new MyViewModel2());
          
    
          mainWindow.DataContext = viewModels;
    
          mainWindow.Show();      
    

    it works, but only for the first view.

    The question is, how can I handle it ?

     

    thx,

    J.

    Wednesday, November 10, 2010 3:16 PM
  • What you would do is put some sort of ItemsControl in your Window (e.g., a vanilla ItemsControl or ListBox) and set bind its ItemsSource property to the ObservableCollection<object>.

    Generally you would have some sort of "MainViewModel" for the entire Window that would contain this ObservableCollection of your sub-ViewModels as a property.  Then you would bind the DataContext of the Window to the MainViewModel, and bind the ItemsControl in the Window to the "viewModels" ObservableCollection.

    Here's some pseudo-XAML:

     

    <Window>

        <Window.Resources>

    <!-- DataTemplates here -->

    <local:MainViewModel x:Key="MainViewModel"/>

        </Window.Resources>

        <Grid DataContext="{Binding Source={StaticResource MainViewModel}}">

            <ItemsControl ItemsSource="{Binding Path=ViewModels}"/>

     

    If you don't want to use an ItemsControl, then ditch the DataTemplates and declare your Views directly, and bind them to their associated properties on the MainViewModel.

    Wednesday, November 10, 2010 4:18 PM