In my previous question I believe I wasn't clear so I didn't get any answer that can help, so maybe I will post some code examples. GreenScreen.xaml
<UserControl x:Class="WPFTut.GreenScreenView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="Green">
<Label Content="{Binding ScreenViewModel.ScreenName}"/>
<Label Content="{Binding ScreenViewModel.UniqueProperty}"/>
</Grid>
RedScreen.xaml
<UserControl x:Class="WPFTut.RedScreenView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Background="Red">
<Label Content="{Binding ScreenViewModel.ScreenName}"/>
</Grid>
Main.xaml
<Window x:Class="WPFTut.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="LayoutRoot">
</Grid>
IScreenViewModel.cs
namespace WPFTut
{
interface IScreenViewModel
{
string ScreenName { get; set; }
}
}
RedScreenViewModel.cs
namespace WPFTut
{
class RedScreenViewModel:IScreenViewModel
{
public string ScreenName
{
get; set;
}
}
}
GreenScreenViewModel.cs
namespace WPFTut
{
class GreenScreenViewModel : IScreenViewModel
{
public string ScreenName { get; set; }
public string UniqueProperty { get; set; }
}
}
ScreenViewModelWrapper.cs
using System.ComponentModel;
namespace WPFTut
{
class ScreenViewModelWrappers : INotifyPropertyChanged
{
private IScreenViewModel screenViewModel;
private IScreenViewModel ScreenViewModel
{
get { return screenViewModel; }
set
{
if (screenViewModel != value)
{
screenViewModel = value;
OnPropertyChanged("ScreenViewModel");
}
}
}
public void SwapViewModel(MainWindow mainWindow)
{
//Yeah it was done statically, but in my original code, it is actually dynamic to switch between
//any screens. Just to keep it simlpe
mainWindow.LayoutRoot.Children.Clear();
mainWindow.LayoutRoot.Children.Add(new GreenScreenView()); // here add randomly chosen screen from array of screens.
mainWindow.UpdateLayout(); //it doesn't refresh the visual tree. So if a red screen was selected next, an exception is thrown
ScreenViewModel = new GreenScreenViewModel(); //
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
var s = new PropertyChangedEventArgs(propertyName);
if (handler != null)
{
handler(this, s);
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
So that's the quick example I could write up. Again, in the ViewModelWrapper the screen is selected dynamically based on user input. Now assuming GreenScreenView was chosen first, when you delete and clear to add RedScreen and you change the ScreenViewModel to RedScreenViewModel when it tries to update the bindings, it still sees the GreenScreenView! Hence it tries to look for this:
<Label Content="{Binding ScreenViewModel.UniqueProperty}"/>
But that code doesn't belong to RedScreenView, so how do I update the visual tree to look at the correct xaml tree? Because it is throwing a NullReferenceException. I really don't know if I can make it any clearer. Thanks again.
Link to previous question: Refresh View databindings using UpdateLayout or some other alternative