I want to create an application with a menu on the left that will change the content on the right. For that, I Have a MainWindow with two ContentControl (One that will Content a UserControl 'Menu' and the other one that will Content the selected UserControl 'Red' or 'Green'.
The problem is that the Content on the right does not Change...
I have made some research and saw concepts like Dependency Injection, Delegate, Event, Message Bus, ViewModelLocator... but I don't know which one would be the most suitable in this case and how to implement it. (I don't want to use MVVMLight or any PlugIn like that)
Thx in advance for your interest.
For that I use the MVVM pattern and DataTemplate Binding:
App.xaml
<Application.Resources>
<DataTemplate DataType="{x:Type viewModel:MainViewModel}">
<view:MainWindow />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModelMenu:LeftViewModel}">
<viewMenu:Left />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModelContent:RedViewModel}">
<viewContent:Red />
</DataTemplate>
</Application.Resources>
ViewModel.cs
public abstract class ViewModel : INotifyPropertyChanged
{
#region Properties
private ViewModel _mainContent;
public ViewModel MainContent
{
get => _mainContent;
set
{
_mainContent = value;
OnPropertyChanged();
MessageBox.Show(nameof(MainContent));
}
}
#endregion Properties
public ViewModel()
{
InitCommands();
}
protected abstract void InitCommands();
#region Factory Method - CreateCommand
protected ICommand CreateCommand(Action execute, Func<bool> canExecute)
{
return new RelayCommand(
execute: execute,
canExecute: canExecute
);
}
protected ICommand CreateCommand<T>(Action<T> execute, Predicate<T> canExecute)
{
return new RelayCommand<T>(
execute: execute,
canExecute: canExecute
);
}
#endregion Factory Method - CreateCommand
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainViewModel.cs
internal class MainViewModel : ViewModel
{
private ViewModel _leftMenu;
public ViewModel LeftMenu
{
get => _leftMenu;
set
{
_leftMenu = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
LeftMenu = new LeftViewModel();
}
protected override void InitCommands()
{
}
LeftViewModel.cs
internal class LeftViewModel : ViewModel
{
public ICommand ChangeContentToRed { get; set; }
public ICommand ChangeContentToGreen { get; set; }
protected override void InitCommands()
{
ChangeContentToRed = new RelayCommand(
execute: () => MainContent = new RedViewModel(),
canExecute: () => !(MainContent is RedViewModel)
);
ChangeContentToGreen = new RelayCommand(
execute: () => MainContent = new GreenViewModel(),
canExecute: () => !(MainContent is GreenViewModel)
);
}
}
RedViewModel and GreenViewModel are empty so I don't show the code but extend ViewModel
Window.xaml
<Window.DataContext>
<viewModel:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0" Content="{Binding Path=LeftMenu}" />
<ContentControl Grid.Column="1" Content="{Binding Path=MainContent}" />
</Grid>
Left.xaml
<UserControl.DataContext>
<viewModel:LeftViewModel />
</UserControl.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button
Grid.Row="0"
Command="{Binding Path=ChangeContentToRed}"
Content="Red" />
<Button
Grid.Row="1"
Command="{Binding Path=ChangeContentToGreen}"
Content="Green" />
</Grid>
Red and Green are only two UserControl with a red and a green grid