I need my SharedViewModel to be set in design time to display data in my UI
as I run the app, I see data on the screen, because OnLoaded runs LoadStuffs
LoadStuffs initiates the SharedViewModel and creates data
but at design time after a rebuild, nothing show up in the designer
<Window x:Class="MyApp.MainWindow"
mc:Ignorable="d"
xmlns:local="clr-namespace:MyApp"
...
Loaded="OnLoaded"
d:DataContext="{Binding RelativeSource={RelativeSource Self}, Path=SharedViewModel}"
>
At runtime, these get executed
void OnLoaded(object sender, RoutedEventArgs e)
{
LoadStuffs();
}
private void LoadStuffs()
{
Logger.Log("LoadStuffs() executed!");
...
SharedViewModel = ...
}
The message "LoadStuffs() executed!" only appears at runtime, never in design
The property of the main class :
private SharedViewModel m_sharedViewModel;
public SharedViewModel SharedViewModel
{
set
{
m_sharedViewModel= value;
}
get
{
Logger.Log("SharedViewModel getter"); <<<<< this is never called as the log.txt is only created at runtime
if (m_sharedViewModel == null)
{
Logger.Log("Initializing DesignSharedViewModel");
LoadStuffs(); // Initializes m_sharedViewModel
}
return m_sharedViewModel;
}
}
Thanks for your help on this
The cleanest way of allocating a ViewModel
to a View
at both design-time and run-time is using the ViewModelLocator
pattern.
1 - Add a class to handle creation of ViewModels.
public class ViewModelLocator
{
public ViewModelLocator()
{
// include any IOC setup here if required.
}
public MainViewModel MainViewModel
{
get
{
return new MainViewModel();
// replace this with a call to the IOC container if any injected servies are required.
}
}
// repeat for any other ViewModel types required.
}
2 - Create an instance of this locator class in App.xaml, making it a application wide resouce.
<Application.Resources>
<local:ViewModelLocator x:Key="ViewModelLocator">
</Application.Resources>
3 - in each View, reference this locator instance as a source for its DataContext
<Window
x:Class="MyApp.MainView"
...
DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=MainViewModel}" />
For a more detailed example including how to have different injected services for design-time and run-time usage, check out my blog post.