Search code examples
c#mvvmviewuwpviewmodel

Multiple ViewModels in same View


I have several different ViewModels that I would like to display in the same view (MainPage.xaml).

I'm new to this and don't know how to do it. I have tried to create a MainViewModel:

    public class MainViewModel : ViewModelBase, INotifyPropertyChanged
    {
        WeatherViewModel weatherView = new WeatherViewModel();
        ForecastViewModel forecastViewModel = new ForecastViewModel();
        DeparturesViewModel departuresViewModel = new DeparturesViewModel();
        CalenderViewModel calenderViewModel = new CalenderViewModel();
    }

    public void GetAllViews()
    {
        weatherView.GetCurrentTemp();
        forecastViewModel.GetForecastTemp();
        departuresViewModel.GetDepartures();
        calenderViewModel.GetCalender();
    }

And in my MainPage.xaml.cs I have this:

     public MainPage()
     {
        this.InitializeComponent();
        this.DataContext = new MainViewModel();
     }

     private void Window_Loaded(object sender, RoutedEventArgs e)
     {
        var vm = this.DataContext as MainViewModel;
        vm.GetAllViews();
     }

I manage to display each ViewModel individually like this instead:

  this.DataContext = new WeatherViewModel();

but I would like to display everything in the same View.


Solution

  • I think you're on the right track but missed some small but important pieces.

    In your example code the MainViewModel class is currently setup with private fields where you really need public properties. Additionally, I would make sure ViewModelBase implements INotifyPropertyChanged if it's not already; that way none of the classes deriving from ViewModelBase need to worry about that part.

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        /* INotifyPropertyChanged implementation +
           whatever other common behavior makes sense
           belongs in this class
        */
    }
    
    public class MainViewModel : ViewModelBase
    {
        public WeatherViewModel Weather { get; } = new WeatherViewModel();
        public ForecastViewModel Forecast { get; } = new ForecastViewModel();
        public DeparturesViewModel Departures { get; } = new DeparturesViewModel();
        public CalendarViewModel Calendar { get; } = new CalendarViewModel();
    }
    

    In your view code behind file you're setting the data context to 2 different instances of MainViewModel - once in the constructor and once in the Loaded event handler. I'd stick with the constructor version or instead you could set the data context in XAML like this:

    <MainPage.DataContext>
        <MainViewModel>
    </MainPage.DataContext>
    

    Once the data context for the main page is setup and the view models are public properties then you can use bindings to access the state (properties) of the view models perhaps something like this:

    <TextBlock Text='{Binding Path=Weather.CurrentTempCelsius, StringFormat='Current Temp: {0}°C'}' />