I am on practice using WPF MVVM with a YouTube video. I made menu buttons in a main window and UserControls, and when I click a menu the UserControl is shown in the main window. The MainViewModel has each ViewModel of the UserControl, and the shown UserControl is changed by changing CurrentView in the MainViewModel.
I want to set the DataContext in the UserControl before it is initialized, but I do not know how. I tried to change ViewModel member values in the MainViewModel, but the actual DataContext member variables in the UserControl are just null.
What I want to ask is how I can set the DataContext in the UserControl when it initialize. Or is there any way to access DataContext from MainWindow?
My Code is below:
Application.xaml
<Application x:Class="Practice.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Practice"
xmlns:viewModel="clr-namespace:Practice.MVVM.ViewModel"
xmlns:view="clr-namespace:Practice.MVVM.View"
Startup="Application_Startup">
<Application.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModel:HomeViewModel}">
<view:HomeView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:UserViewModel}">
<view:UserView/>
</DataTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="Practice.MainWindow"
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"
xmlns:local="clr-namespace:Practice"
xmlns:viewModel="clr-namespace:Practice.MVVM.ViewModel"
xmlns:view="clr-namespace:Practice.MVVM.View"
mc:Ignorable="d"
Title="Practice" MinHeight="800" MinWidth="1200"
WindowStyle="None"
ResizeMode="NoResize"
Background="Transparent"
AllowsTransparency="True"
Loaded="Window_Loaded">
<Window.DataContext>
<viewModel:MainViewModel/>
</Window.DataContext>
<Border Background="#002241"
CornerRadius="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="Logo"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
Foreground="White"/>
<Grid Grid.Row="1" Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="75"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<RadioButton Content="Home"
Height="50"
Foreground="White"
FontSize="16"
IsChecked="True"
Command="{Binding HomeViewCommand}"/>
<RadioButton Content="Users"
Height="50"
Foreground="White"
FontSize="16"
Command="{Binding UserViewCommand}"/>
</StackPanel>
</Grid>
<ContentControl Grid.Row="1" Grid.Column="1"
x:Name="CC_View"
Margin="10"
Content="{Binding CurrentView}"/>
</Grid>
</Border>
</Window>
HomeView.xaml
<UserControl x:Class="Practice.MVVM.View.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Practice.MVVM.View"
xmlns:viewModel="clr-namespace:Practice.MVVM.ViewModel"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<viewModel:HomeViewModel/>
</UserControl.DataContext>
<Grid>
</Grid>
</UserControl>
ObservableObject.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Practice.Core
{
public class ObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
RelayCommand.cs
using System;
using System.Windows.Input;
namespace Practice.Core
{
public class RelayCommand:ICommand
{
private Action<object> _execute;
private Func<object, bool> _canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
MainViewModel.cs
namespace Practice.MVVM.ViewModel
{
public class MainViewModel : ObservableObject
{
public RelayCommand HomeViewCommand { get; set; }
public RelayCommand UserViewCommand { get; set; }
public HomeViewModel HomeVM { get; set; }
public UserViewModel UserVM { get; set; }
private object _currentView;
private object parameter1;
private object parameter2;
private object parameter3;
public object CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
parameter1 = new object();
parameter2 = new object();
parameter3 = new object();
HomeVM = new HomeViewModel();
HomeVM.Initialize(parameter1, parameter2, parameter3);
UserVM = new UserViewModel();
CurrentView = HomeVM;
HomeViewCommand = new RelayCommand(o =>
{
CurrentView = HomeVM;
});
UserViewCommand = new RelayCommand(o =>
{
CurrentView = UserVM;
});
}
}
}
HomeViewModel.cs
namespace Practice.MVVM.ViewModel
{
public class HomeViewModel : ObservableObject
{
private object _parameter1;
private object _parameter2;
private object _parameter3;
public HomeViewModel()
{
}
public void Initialize(object parameter1, object parameter2, object parameter3)
{
_parameter1= parameter1;
_parameter2= parameter2;
_parameter3= parameter3;
}
}
}
Thank you in advance.