Reputation: 1
I just start looking into WPF and MVVM, and I'm considering I need to start using MVVM.
I have a winform application, with a main panel, on the left of the main panel there are some buttons, on the right side of the main panel is a zone to place different child panels(one panel at one time), after clicking a main forms botton, a child panel's method will be called.
Is it possible to use MVVM to do such layout and operations?
Upvotes: 0
Views: 297
Reputation: 132568
The main ViewModel would contain properties for
ViewModelBase CurrentPage
ICommand ChangePageCommand
ObservableCollection<ViewModelBase> AvailablePages
The main View would contain
ContentControl
for hosting the CurrentPage
AvailablePages
Clicking a link in the Menu area would call the ChangePage
command to switch the CurrentPage
to the selected AvailablePage
.
DataTemplates
would be used to display ChildViews based on what ChildViewModel is being displayed in CurrentPage
Since the main ViewModel has access to all available pages, it can execute methods on the ChildViewModels if needed, and the ChangePageCommand
can be called from the ChildViewModels
I wrote an example of such an interface here if you're interested, although it only shows an example of switching the CurrentPage
, not navigating through AvailablePages
Upvotes: 1
Reputation: 10347
Sorry for misunderstanding at the first time. I've created a small sample. Here's the XAML code:
<Window x:Class="S4SO.ContainerBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="520" Width="425">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="80" />
<RowDefinition Height="400" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<ContentControl Content="{Binding ContentContent}" Grid.Row="1" Height="400" Width="400" />
<StackPanel Orientation="Horizontal">
<Button Content="Use button" Command="{Binding UseButton}" />
<Button Content="Use Textbox" Command="{Binding UseTextbox}" />
</StackPanel>
</Grid>
</Window>
The window is bound to a viewmodel, For simplicity I took MVVMLight as base:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Controls;
using System.Windows;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight;
namespace S4SO.ContainerBinding {
public class ViewModel : ViewModelBase {
private object _ContentContent;
public object ContentContent {
get { return _ContentContent; }
set {
if ( _ContentContent.GetType() == value.GetType() )
return;
_ContentContent = value;
RaisePropertyChanged( "ContentContent" );
}
}
public ICommand UseButton { get; set; }
public void CommandUseButton () {
ContentContent = new Button() {
Content = "A button",
Width = 400,
Height = 400,
VerticalContentAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center
};
}
public bool CanUseButton () {
return !( _ContentContent is Button );
}
public ICommand UseTextbox { get; set; }
public void CommandUseTextbox () {
ContentContent = new TextBox() {
Text = "Content here",
Width = 400,
Height = 400,
VerticalContentAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center
};
}
public bool CanUseTextbox () {
return !( _ContentContent is TextBox );
}
public ViewModel () {
_ContentContent = new Label() {
Content = "Please choose content!",
Width = 400,
Height = 400,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center
};
UseButton = new RelayCommand( () => CommandUseButton(), () => CanUseButton() );
UseTextbox = new RelayCommand( () => CommandUseTextbox(), () => CanUseTextbox() );
}
}
}
Definitely not production level, but it shows a direction and hopefully is now more what you asked for. I have used simple controls and did not dig into binding those dynamically created controls. Binding via code behind isn't straightforward like binding syntax in XAML. I'll keep that up to you if this is the right direction.
Upvotes: 0
Reputation: 8748
Sure. Both the left and the right panels will be bound to a single ViewModel (which is the VM which represents the current panel on the right). The buttons on the left will call operations (probably via commands) on the ViewModel.
When the active VM changes (ie, when a different panel is shown on the right side) then the data context of the left panel is changed to the new VM.
You will probably want some kind of container VM to represent the whole window, with several child ViewModels representing each of the possible panels on the right. Only one of these is set as the active panel at any given time. Does this make sense?
Upvotes: 1