0

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

Community
  • 1
  • 1
Lews Therin
  • 10,907
  • 4
  • 48
  • 72
  • 1
    Did you initialize the `DataContext` property of your UserControls? And shouldn't the UserControls have a `ScreenViewModel` property? –  Jun 26 '12 at 07:54
  • 6
    Just FYI, this is far from idiomatic WPF and MVVM. You'd be much better off just exposing a `Content` property from your VM and having a `ContentControl` bind to it. No need to mess with the visual tree yourself in your VM - let WPF take care of that. – Kent Boogaart Jun 26 '12 at 08:07
  • Thanks, you set me on right path. – Lews Therin Jun 26 '12 at 13:36
  • Also thanks fmunkert. I keep forgetting about that – Lews Therin Jun 26 '12 at 13:57

0 Answers0