0

I'm not sure if I asked the question correctly, because I am not finding the answer by searching the internet. I am creating a wizard window. I have a window that has a title at the top and buttons at the bottom that will stay there throughout changing the pages. So in the xaml.cs for the window, I have a list of UserControls that will contain all of the views for the wizard. I also have a property/field that holds the current view. I want to create a xaml UserControl tag that binds to the current view property. It should change when I change the current view property (I have already implemented the INotifyChanged interface). The current view property will be changed by c#. Here is the code that I have(simplified to show whats needed), and when I run it nothing shows in the view area:

WizardWindow.xaml:

<Window x:Class="WizardWindow.WizardWindow"...>
    <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="70"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="50"/>
    </Grid.RowDefinitions>
    <Grid Grid.Row="0">
        <TextBlock Text="Wizard Title"/>
    </Grid>
    <Grid Grid.Row="1">
        <Border Name="WizardWindowPageContent" Margin="5" BorderBrush="Black" BorderThickness="1">


            <!--This is what I have tried but isn't working -->
            <UserControl Content="{Binding CurrentView}" />


        </Border>
    </Grid>
    <Grid Grid.Row="2" Name="WizardButtons">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Button Grid.Column="0">Cancel</Button>
        <Button Grid.Column="2">Back</Button>
        <Button Grid.Column="3">Next</Button>
    </Grid>
</Grid>
</Window>

WizardWindow.xaml.cs:

using System;
...
using System.Windows.Controls;

namespace WizardWindow
{
    public partial class WizardWindow : Window, INotifyPropertyChanged
    {
        // List of views in the config window
        private List<UserControl> views;

        // Current view showing in the window
        private UserControl currentView;
        public UserControl CurrentView
        {
            get { return currentView; }
            set
            {
                currentView = value;
                OnPropertyChanged("CurrentView");
            }
        }

        // Used to keep track of the view index 
        private int viewIndex;

        public WizardWindow ()
        {
            InitializeComponent();
            // Set the screen to the center of the screen
            WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;

            views = new List<UserControl>();

            views.Add(new FirstWizardPage(this));

            viewIndex = 0;
            CurrentView = views[viewIndex];
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string info)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(info));
            }
        }
    }
}

FirstWizardPage.xaml:

<!-- This should show up in the window -->
<UserControl x:Class="WizardWindow.FirstWizardPage" ... >
    <Grid>
            <TextBlock>Lorem Ipsum ...</TextBlock>
    </Grid>
</UserControl>

FirstWizard.xaml.cs:

using System.Windows.Controls;

namespace WizardWindow
{
    public partial class FirstWizardPage : UserControl
    {
        public FirstWizardPage(WizardWindow window)
        {
            InitializeComponent();
        }
    }
}

The given possible duplicate, Window vs Page vs UserControl for WPF navigation? , is a good solution if I wanted to rewrite my program. However, it is not a solution to my exact problem. Someone else might have a similar problem and need this solution.

kingcobra1986
  • 971
  • 2
  • 14
  • 38
  • Possible duplicate of [Window vs Page vs UserControl for WPF navigation?](https://stackoverflow.com/questions/12206120/window-vs-page-vs-usercontrol-for-wpf-navigation) – ASh Feb 21 '18 at 11:39
  • You seem to be reinventing the wheel. See [Navigation Overview](https://learn.microsoft.com/en-us/dotnet/framework/wpf/app-development/navigation-overview). – Clemens Feb 21 '18 at 11:41

2 Answers2

1

you need to use this:

<ContentControl x:Name="MyView"
                Content="{Binding CurrentView}" />

It should work for you, but it's not MVVM.

Marco
  • 984
  • 10
  • 18
1

You must binding on property DataContext of your user control, if you want to use MVVM. I Will show little example for you:

It is MainWindow.xaml:

<Window x:Class="WpfApp2.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:WpfApp2"
    xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <local:Foo DataContext="{Binding UserControlViewModel}"/>
</Grid>

It is MainWindow.xaml.cs:

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        DataContext = new MainWindowViewModel();
    }

}

It is MainWindowViewModel.cs:

 public class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        UserControlViewModel = new UserControlViewModel{ Name = "Hello World" };
    }
    public UserControlViewModel UserControlViewModel { get; }
}

It is Foo.xaml:

<UserControl x:Class="WpfApp2.Foo"
         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:WpfApp2"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
       <TextBlock Text="{Binding Name}"/> 
</Grid>

It is FooUsercontrolViewModel.cs

public class FooUserControlViewModel
{
    public string Name { get; set; }
}
  • Thank you for the detailed description on how to use MVVM in this context. However, I am to far into this project to rebuild everything. – kingcobra1986 Feb 21 '18 at 23:46