1

I'm quite new to WPF and what I'm trying to do is switch views through different command buttons.. this is my current code...

Basically I have two buttons in my MainView, SetupLan and SetupSerialPort. For simplicity, I'm currently trying to make SetupSerialPort working first. But when I click the button for it, the command executes but the view doesn't change...

App.xaml

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModels:MainViewModel}">
        <Views:MainView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:SetupLanViewModel}">
        <Views:SetupLanView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:SetupSerialPortViewModel}">
        <Views:SetupSerialPortView />
    </DataTemplate>
</Application.Resources>

MainWindow.xaml

<Grid>
    <ContentControl Content="{Binding}" />
</Grid>

MainWindow.xaml.cs

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

MainViewModel

public DisplaySetupSerialPortCommand SetupSerialPort
{
    get; set;
}

public MainViewModel()
{
    SetupSerialPort = new DisplaySetupSerialPortCommand(this);
}

MainView

<StackPanel>
    <Button Height="50" Width="150" HorizontalAlignment="Left"Command="{Binding SetupLan}">Lan</Button>
    <Button Height="50" Width="150" HorizontalAlignment="Left" Command="{Binding SetupSerialPort}">Serial Port</Button>
</StackPanel>

DisplaySetupSerialPortCommand

class DisplaySetupSerialPortCommand : ICommand
{
    private BaseViewModel _baseViewModel;

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public DisplaySetupSerialPortCommand(BaseViewModel baseViewModel)
    {
        _baseViewModel = baseViewModel;
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        _baseViewModel.ViewModel = new SetupSerialPortViewModel();
    }
}
2
  • Are you looking to have SetupLan and SetupSrialPort be interchangeable? Commented Apr 20, 2016 at 15:00
  • @d.moncada There's a separate view for both setups. and I'm also planning to have separate commands for it. Say for serialport, when the serialport button is pressed, it will execute the serial port command and show the serial port view. Commented Apr 20, 2016 at 15:19

1 Answer 1

1

A few things.

Your command is not doing anything at all, it's simply just creating a ViewModel. You need to add additional logic for this to work.

If you want to switch out the DataTemplate to different views, you will need to implement some type of Trigger.

First, update your DataTemplates to have an associated key.

<Application.Resources>
    <DataTemplate DataType="{x:Type ViewModels:MainViewModel}" x:Key="MainView">
        <Views:MainView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:SetupLanViewModel}" x:Key="Lan">
        <Views:SetupLanView />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:SetupSerialPortViewModel}" x:Key="SerialPort">
        <Views:SetupSerialPortView />
    </DataTemplate>
</Application.Resources>

By adding a key, it will allow you to reference each one, where/when needed.

Next, inside your MainWindow.xaml, this is where the Triggers will occur. Update your ContentControl to Trigger and switch it's DataTemplate based on some condition. In this case, the condition I created is called ViewType.

<Grid>
    <ContentControl Content="{Binding}">
        <ContentControl.Style>
            <Style TargetType="ContentControl">
                <Setter Property="ContentTemplate" Value="{StaticResource MainView}" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding ViewType}" Value="SerialPort">
                        <Setter Property="ContentTemplate" Value="{StaticResource SerialPort}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding ViewType}" Value="Lan">
                        <Setter Property="ContentTemplate" Value="{StaticResource Lan}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</Grid>

Lastly, you will need to have a ViewType property, and set that property based on the specific command that was executed. Add to ViewType property your BaseViewModel since the command has a reference to this.

public string ViewType
{
    get { return _viewType; }
    set
    {
        _viewType = value;
        RaisePropertyChanged();
    }
}

Now, you can change the ViewType whenever the command is clicked.

public void Execute(object parameter)
{
    _baseViewModel.ViewType = "SerialPort";
    _baseViewModel.ViewModel = new SetupSerialPortViewModel();
}  

Note: I used a string for a ViewType type just for demo purposes only. You would probably want to use an enumeration instead.

Sign up to request clarification or add additional context in comments.

5 Comments

Where did RaisePropertyChanged() come from?
I tried your solution but commenting out RaisePropertyChanged().. though nothing happens, button still executes but the view doesn't change
It's working now :) so I needed to implement INotifyPropertyChanged to BaseViewModel and raise that PropertyChanged event when the viewType changes.
Thank you very much!. I just want to ask if you know any resources/links that tackles WPF concepts (for beginners)..
Yep, I assumed you had implemented INotifyPropertyChanged already in your BaseViewModel (which is what most do). Regarding resources for beginners, WPF unleashed is a pretty good book.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.