views:

46

answers:

3

Hi,

I want to use MVVM approach to achieve something like below:

I have a MainWindow where i have a 3 Buttons like: a)Customers b) Orders c) Sales

By clicking on button, it should open its respective window/usercontrol xaml with customers details,orders details,sales details.

I have tried everything but culdnt able to do so.

How to achieve this using MVVM pattern. Kindly provide the solution?

Thanks

A: 

The answer depends on how you want your Customers, Orders and Sales views displayed. If you want them displayed in the same view, simply add a content control bound to a property in your main ViewModel.

For example, if you're using the MVVM Light Toolkit, your MainPage.xaml might look like...

<UserControl x:Class="MvvmLight2.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             Height="300"
             Width="300"
             DataContext="{Binding Main, Source={StaticResource Locator}}">

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Skins/MainSkin.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <StackPanel Orientation="Vertical">

        <StackPanel Orientation="Horizontal">
            <Button Content="Customers" Command="{Binding DisplayView}" CommandParameter="Customers" Margin="10" />
            <Button Content="Orders" Command="{Binding DisplayView}" CommandParameter="Orders" Margin="10" />
            <Button Content="Sales" Command="{Binding DisplayView}" CommandParameter="Sales" Margin="10" />
        </StackPanel>

        <ContentControl Content="{Binding CurrentView}" IsTabStop="False" Margin="10" />

    </StackPanel>
</UserControl>

And your MainPageViewModel would be...

using System.Windows.Controls;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

namespace MvvmLight2.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            DisplayView = new RelayCommand<string>(DisplayViewCommandExecute);
        }

        #region Commands

        public RelayCommand<string> DisplayView { get; private set; }

        #endregion

        #region CurrentView Property

        public const string CurrentViewPropertyName = "CurrentView";

        private UserControl _currentView;

        public UserControl CurrentView
        {
            get { return _currentView; }
            set
            {
                if (_currentView == value)
                    return;

                _currentView = value;
                RaisePropertyChanged(CurrentViewPropertyName);
            }
        }

        #endregion

        private void DisplayViewCommandExecute(string viewName)
        {
            switch (viewName)
            {
                case "Customers":
                    CurrentView = new CustomersView();
                    break;
                case "Orders":
                    CurrentView = new OrdersView();
                    break;
                case "Sales":
                    CurrentView = new SalesView();
                    break;
            }
        }
    }
}

This all assumes that you have created views and view models for Customers, Orders, and Sales, and modified the ViewModelLocator to include them.

At this point, if you need to display specific information in your child views, you can create a dependency property in them, and set that from your MainViewModel before you display the view.

Matt Casto
Thanks for the reply. I am new to this MVVM design pattern so i am not getting exactly where to put what. and how to call the commands and all. Also where to set datacontext of what window. Kindly suggest? Thanks
Tarun
Take a look at the MVVM Light Toolkit (http://mvvmlight.codeplex.com/). It provides guidance for all of your questions.
Matt Casto
Hi Matt,How to modified the ViewModelLocator to achieve this?Kindly Suggest?Thanks
Tarun
A: 

Thanks for the reply. I am not getting where to bind the customer button that I placed in the MainWindow.xaml in xaml or some cs file. I have this hierarchy: in View folder -- Customer.xaml file

in ViewModel folder -- CustomerViewModel.cs

in root -- MainWindow.xaml. In this, I have the Customer Button

I am using RelayCommand.cs to fire the button click event

In CustomerViewModel.cs file, I have put

public class CustomerViewModel { public RelayCommand CustomerCommand {

get { return new RelayCommand(param => { return true; }, param => { OpenCustomer(); }); }

}

private void OpenCustomer() {

//some code }

} Kindly Suggest,

Thanks.

Tarun
It looks like you've got the parameters to your CustomerCommand ctor call switched. The execute Action is first, and the canexecute Action is second. Also, you don't have to provide a canexecute action if its always going to execute. Just ahve your CustomerCommand return new RelayCommand(OpenCustomer);
Matt Casto
A: 

You may want to look into the mediator pattern . Common implementations are the Messenger class in the MVVM Light Toolkit and Event Aggregation in PRISM.

One basic workflow using this pattern... Command is called on viewmodel1. Viewmodel1 registers some message with the mediator. Viewmodel2 subscribes to that message and does something in response (like creates new view2 or changes visual state of the view2).

Brandon Copeland