DataContext Switching for 2 different ViewModels using Frame @Hui Lui-MSFT

saurabh alliumsepa 20 Reputation points
2023-11-17T04:13:23.8166667+00:00

Hello @Hui Liu-MSFT

I have created 2 View Buttons. In View1 I am able to increment the 2 texts and can view the result. In View2, I am able to drag and drop multiple copies of TextBlock into Canvas region and can change its width and height property from handycontrol. I navigated to View1 and was able to view the change. However, on again navigating to View2 I cannot see multiple instances of Textblocks at its various positions in the Canvas which I did. Indeed the default View2 is there with texblock at left, Canvas at middle and handycontrol in right. WHere is the problem and how should I tackle this. The code is provided below.

Commands.cs:

using P1_DataSwitching.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace P1_DataSwitching.Commands
{
    public class RelayCommand : ICommand
    {
        private readonly Action _execute;
        private readonly Func<bool> _canExecute;

        public event EventHandler CanExecuteChanged;

        public RelayCommand(Action execute, Func<bool> canExecute = null)
        {
            _execute = execute ?? throw new ArgumentNullException(nameof(execute));
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute();
        }

        public void Execute(object parameter)
        {
            _execute();
        }

        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }
    }
}

-------------------------------------------------------------------------------------------
UC_Tb.xaml:

<UserControl x:Class="P1_DataSwitching.View.UC_Tb"
             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:P1_DataSwitching.View"
             mc:Ignorable="d" 
             x:Name="UC_Add"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBox Text="{Binding Number, ElementName=UC_Add}" />
    </Grid>
</UserControl>

-------------------------------------------------------------------------------------------
UC_Tb.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace P1_DataSwitching.View
{
    /// <summary>
    /// Interaction logic for UC_Tb.xaml
    /// </summary>
    public partial class UC_Tb : UserControl
    {
        public UC_Tb()
        {
            InitializeComponent();
        }

        public string Number
        {
            get { return (string)GetValue(NumberProperty); }
            set { SetValue(NumberProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Number.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty NumberProperty =
            DependencyProperty.Register("Number", typeof(string), typeof(UC_Tb), new PropertyMetadata(null));


    }
}

-------------------------------------------------------------------------------------------
UC1.xaml:

<UserControl x:Class="P1_DataSwitching.View.UC1"
             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:P1_DataSwitching.View"
             xmlns:v="clr-namespace:P1_DataSwitching.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <StackPanel>
        <TextBlock Text="Number1" Margin="5" />
        <!--<local:UC_Add Number="{Binding Text1}" Margin="5" />-->
        <v:UC_Tb Number="{Binding Text1}" Margin="5" />

        <TextBlock Text="Number2" Margin="5" />
        <!--<local:UC_Add Number="{Binding Text2}" Margin="5" />-->
        <v:UC_Tb Number="{Binding Text2}" Margin="5" />

        <TextBlock Text="Addition of Number1 and Number2" Margin="5" />
        <!--<local:UC_Add Number="{Binding Sum}" Margin="5" />-->
        <v:UC_Tb Number="{Binding Sum}" Margin="5" />

        <Button Content="Increment Text1" Command="{Binding IncrementNum1Command}" Margin="5" />
        <Button Content="Increment Text2" Command="{Binding IncrementNum2Command}" Margin="5" />
    </StackPanel>
</UserControl>

-------------------------------------------------------------------------------------------
UC1.xaml.cs:

using P1_DataSwitching.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace P1_DataSwitching.View
{
    /// <summary>
    /// Interaction logic for UC1.xaml
    /// </summary>
    public partial class UC1 : UserControl
    {
    //    UC1_ViewModel myviewmodel = new UC1_ViewModel();
        public UC1()
        {
            InitializeComponent();
     //       this.DataContext = myviewmodel;
        }

       
    }
}

-------------------------------------------------------------------------------------------
UC2.xaml:

<UserControl x:Class="P1_DataSwitching.View.UC2"
             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:P1_DataSwitching.View"
             xmlns:v="clr-namespace:P1_DataSwitching.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>
        <Border BorderBrush="Blue" BorderThickness="1">
            <Canvas x:Name="canvas1"
                    AllowDrop="True"
                    Background="Transparent">
                <v:UC3 x:Name="Tb1" Canvas.Left="4" />
            </Canvas>
        </Border>
        <v:UC4 Grid.Column="2" />

        <v:UC5 ScrollViewer.VerticalScrollBarVisibility="Visible" 
               Grid.Column="1"  Margin="5" />
    </Grid>
</UserControl>

-------------------------------------------------------------------------------------------
UC2.xaml.cs:

using P1_DataSwitching.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace P1_DataSwitching.View
{
    /// <summary>
    /// Interaction logic for UC2.xaml
    /// </summary>
    public partial class UC2 : UserControl
    {
        UC2_ViewModel mymodel;
        public UC2()
        {
            InitializeComponent();
            mymodel = new UC2_ViewModel();
            this.DataContext = mymodel;
        }
    }
}

-------------------------------------------------------------------------------------------
UC3.xaml:

<UserControl x:Class="P1_DataSwitching.View.UC3"
             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:P1_DataSwitching.View"
             mc:Ignorable="d" 
             d:DesignHeight="200" d:DesignWidth="200">
    <Border BorderBrush="Red" BorderThickness="2">
        <Canvas x:Name="canvas2" AllowDrop="True" 
                Background="Transparent">
            <TextBlock Width="100"
                       Height="100" 
                       Margin="5" 
                       Background="Gray" 
                       MouseMove="TextBlock_MouseMove"
                       />
        </Canvas>
    </Border>
</UserControl>

-------------------------------------------------------------------------------------------
UC3.xaml.cs:

using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Xml;

namespace P1_DataSwitching.View
{
    /// <summary>
    /// Interaction logic for UC3.xaml
    /// </summary>
    public partial class UC3 : UserControl
    {
        public UC3()
        {
            InitializeComponent();
        }

        private void TextBlock_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
            {
                GlobalVariable.MyCheck = 0;
                var xaml = XamlWriter.Save(sender);
                var xamlString = new StringReader(xaml);
                var xmlTextReader = new XmlTextReader(xamlString);
                var deepCopyObject = XamlReader.Load(xmlTextReader);

                DragDrop.DoDragDrop(sender as DependencyObject, new DataObject(DataFormats.Serializable, deepCopyObject), DragDropEffects.Move);
            }
        }
    }
}

-------------------------------------------------------------------------------------------
UC4.xaml:

<UserControl x:Class="P1_DataSwitching.View.UC4"
             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:P1_DataSwitching.View"
             mc:Ignorable="d" 
             xmlns:hc="https://handyorg.github.io/handycontrol"
             d:DesignHeight="600" d:DesignWidth="400">
    <Grid>
        <hc:PropertyGrid 
            x:Name="mypg"  
            Margin="10,0,10,0"
            SelectedObject="{Binding SelectedTb}"
            />
    </Grid>
</UserControl>

-------------------------------------------------------------------------------------------

UC4.xaml.cs:

using P1_DataSwitching.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace P1_DataSwitching.View
{
    /// <summary>
    /// Interaction logic for UC4.xaml
    /// </summary>
    public partial class UC4 : UserControl
    {
        public UC4()
        {
            InitializeComponent();
        }

        public void MyselectedObject1()
        {
            UC2_ViewModel.currentprop.SelectedTb = GlobalVariable.SelectedViewModel;
        }
    }
}

-------------------------------------------------------------------------------------------

UC5.xaml:

<UserControl x:Class="P1_DataSwitching.View.UC5"
             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:P1_DataSwitching.View"
             mc:Ignorable="d" 
             d:DesignHeight="800" d:DesignWidth="450">
    <Border Margin="5" BorderBrush="Green" BorderThickness="2">
        <Canvas 
                Background="LightBlue"
                AllowDrop="True"
                x:Name="canvas"
            MouseDown="canvas_MouseDown"
            Drop="canvas_Drop"
            MouseMove="canvas_MouseMove"
         />
    </Border>
</UserControl>

-------------------------------------------------------------------------------------------
UC5.xaml.cs:

using P1_DataSwitching.ViewModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace P1_DataSwitching.View
{
    /// <summary>
    /// Interaction logic for UC5.xaml
    /// </summary>
    public partial class UC5 : UserControl
    {
        UC2_ViewModel vmt;
        UC4 mypg;
        int check;
        public UC5()
        {
            InitializeComponent();
            vmt = new UC2_ViewModel();
            this.DataContext = vmt;
            mypg = new UC4();
        }

        private Point mousePosition;
        private void canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                //  startPoint = e.GetPosition(null); // Save the initial click position
                check = 1;
                mousePosition = e.GetPosition(canvas);
                Method_SelectedControl(e);

                //    DragDrop.DoDragDrop(vmt.SelectedControl, vmt.SelectedControl, DragDropEffects.Move);
            }
        }

        private void Method_SelectedControl(MouseButtonEventArgs e)
        {
            vmt.SelectedControl = e.OriginalSource as UIElement;

            vmt.Height = ((FrameworkElement)vmt.SelectedControl).Height.ToString();
            vmt.Width = ((FrameworkElement)vmt.SelectedControl).Width.ToString();
            GlobalVariable.SelectedViewModel = vmt;

            mypg.MyselectedObject1();
        }

        private void canvas_Drop(object sender, DragEventArgs e)
        {
            if (check == 1 && GlobalVariable.MyCheck == 1)
            {

                // UIElement element = e.OriginalSource as UIElement;
                Point dropPosition = e.GetPosition(canvas);
                Canvas.SetLeft(vmt.SelectedControl, dropPosition.X);
                Canvas.SetTop(vmt.SelectedControl, dropPosition.Y);
                check = 0;
                GlobalVariable.MyCheck = 0;
            }
            else
            {
                Object data = e.Data.GetData(DataFormats.Serializable);
                if (data is UIElement element)
                {
                    Point dropPosition = e.GetPosition(canvas);
                    Canvas.SetLeft(element, dropPosition.X);
                    Canvas.SetTop(element, dropPosition.Y);
                    if (!canvas.Children.Contains(element))
                    {
                        canvas.Children.Add(element);
                    }
                }
                GlobalVariable.MyCheck = 1;
            //    GlobalVariable.SelectedControl = data as UIElement;
                //vmt.Height = ((FrameworkElement)vmt.SelectedControl).Height.ToString();
                //vmt.Width = ((FrameworkElement)vmt.SelectedControl).Width.ToString();
                //GlobalVariable.SelectedViewModel = vmt;

                mypg.MyselectedObject1();
            }
        }

        private void canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && check == 1)
            {

                var position = e.GetPosition(canvas);
                var offset = position - mousePosition;
                mousePosition = position;
                Canvas.SetLeft(vmt.SelectedControl, Canvas.GetLeft(vmt.SelectedControl) + offset.X);
                Canvas.SetTop(vmt.SelectedControl, Canvas.GetTop(vmt.SelectedControl) + offset.Y);
            }
        }
    }
}

-------------------------------------------------------------------------------------------
BaseViewModel.cs:

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace P1_DataSwitching.ViewModel
{
    public class BaseViewModel : INotifyPropertyChanged
    {


        //Method for property change at run time
        public event PropertyChangedEventHandler PropertyChanged;
        public virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }


    }
}

-------------------------------------------------------------------------------------------
MainViewModel.cs:

using P1_DataSwitching.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace P1_DataSwitching.ViewModel
{
    public class MainViewModel: BaseViewModel
    {
        UC1_ViewModel myuc1viewmodel;
        UC2_ViewModel myuc2viewmodel;

        // SelectedViewModel property controls the navigation between view models
        private BaseViewModel _selectedViewModel;

		public BaseViewModel SelectedViewModel
		{
			get { return _selectedViewModel; }
			set { 
				_selectedViewModel = value;
                OnPropertyChanged(nameof(SelectedViewModel));
            }
		}

        public ICommand SwitchToUC1Command { get; }
        public ICommand SwitchToUC2Command { get; }

        public MainViewModel()
        {
            //UpdateViewCommands = new UpdateViewCommand(this);
            myuc1viewmodel = new UC1_ViewModel();
            myuc2viewmodel = new UC2_ViewModel();

            SwitchToUC1Command = new RelayCommand(SwitchToUC1);
            SwitchToUC2Command = new RelayCommand(SwitchToUC2);
        }

        private void SwitchToUC1()
        {
            // Set the stored instance of UC1ViewModel as the current view model
            SelectedViewModel = myuc1viewmodel;
        }

        private void SwitchToUC2()
        {
            // Set the stored instance of UC2ViewModel as the current view model
            SelectedViewModel = myuc2viewmodel;
            GlobalVariable.SelectedViewModel = SelectedViewModel;
        }

    }
}

-------------------------------------------------------------------------------------------
UC1_ViewModel.cs:

using P1_DataSwitching.Commands;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace P1_DataSwitching.ViewModel
{
    public class UC1_ViewModel:BaseViewModel
    {

        #region Text1
        private int MyText1 = 30;

        public int Text1
        {
            get
            {
                return MyText1;
            }
            set
            {
                MyText1 = value;
                OnPropertyChanged(nameof(Text1));
                OnPropertyChanged(nameof(Sum));
            }
        }

        #endregion

        #region Text2
        private int MyText2 = 40;

        public int Text2
        {
            get
            {
                return MyText2;
            }
            set
            {
                MyText2 = value;
                OnPropertyChanged(nameof(Text2));
                OnPropertyChanged(nameof(Sum));
            }
        }

        #endregion

        #region Sum
        int _sum = 0;
        public int Sum
        {
            get
            {
                try
                {
                    return Text1 + Text2;
                }
                catch (FormatException)
                {
                    return 0;
                }
            }

        }
        #endregion

        public ICommand IncrementNum1Command { get; }
        public ICommand IncrementNum2Command { get; }

        public UC1_ViewModel()
        {
            IncrementNum1Command = new RelayCommand(IncrementNum1);
            IncrementNum2Command = new RelayCommand(IncrementNum2);
        }
        private void IncrementNum1()
        {
            Text1++;
        }

        private void IncrementNum2()
        {
            Text2++;
        }

    }
}

-------------------------------------------------------------------------------------------
UC2_ViewModel.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace P1_DataSwitching.ViewModel
{
    public class UC2_ViewModel: BaseViewModel
    {
        public static UC2_ViewModel currentprop { get; set; }
        public UC2_ViewModel()
        {
            currentprop = this;
        }

        #region Making By default these properties as false on loading
        // These properties will be hidden by default in the PropertyGrid
        [Browsable(false)]
        public System.Windows.Threading.Dispatcher Dispatcher { get; set; }

        [Browsable(false)]
        public bool IsSealed { get; set; }

        [Browsable(false)]
        public System.Windows.DependencyObjectType DependencyObjectType { get; set; }

        #endregion

        // properties definition

        /// <summary>
        /// Selected Control
        /// </summary>
        private UIElement _selectedControl;
        [Browsable(false)]
        public UIElement SelectedControl
        {
            get { return _selectedControl; }
            set
            {
                _selectedControl = value;

                OnPropertyChanged("SelectedControl");
            }
        }

        private Object _selectedTb;
        [Browsable(false)]
        public Object SelectedTb
        {
            get { return _selectedTb; }
            set
            {
                if (_selectedTb != value)
                {
                    _selectedTb = value;
                    OnPropertyChanged(nameof(SelectedTb));
                }
            }
        }


        #region Width
        private string _tbWidth;
        [Category("Size")]
        public string Width
        {
            get { return _tbWidth; }
            set
            {
                _tbWidth = value;
                if (SelectedControl != null)
                {
                    if (SelectedControl is TextBlock tblock)
                    {
                        if (_tbWidth != "")
                        {

                            tblock.Width = Convert.ToDouble(_tbWidth);
                        }

                    }
                }
                OnPropertyChanged("Width");
            }
        }
        #endregion

        #region Height
        private string _tbHeight;
        [Category("Size")]
        public string Height
        {
            get { return _tbHeight; }
            set
            {
                _tbHeight = value;
                if (SelectedControl != null)
                {
                    if (SelectedControl is TextBlock tblock)
                    {
                        if (_tbHeight != "")
                        {

                            tblock.Height = Convert.ToDouble(_tbHeight);
                        }

                    }

                }
                OnPropertyChanged("Height");
            }
        }
        #endregion

    }
}

-------------------------------------------------------------------------------------------

App.xaml:

<Application x:Class="P1_DataSwitching.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:P1_DataSwitching"
             xmlns:views="clr-namespace:P1_DataSwitching.View"
             xmlns:viewmodels="clr-namespace:P1_DataSwitching.ViewModel"
             xmlns:hc="https://handyorg.github.io/handycontrol"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <hc:ThemeResources/>
                <hc:Theme/>
            </ResourceDictionary.MergedDictionaries>
            <DataTemplate DataType="{x:Type viewmodels:UC1_ViewModel}">
                <views:UC1/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewmodels:UC2_ViewModel}">
                <views:UC2/>
            </DataTemplate>
        </ResourceDictionary>
    </Application.Resources>
</Application>

-------------------------------------------------------------------------------------------
GlobalVariable.cs:

using P1_DataSwitching.ViewModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace P1_DataSwitching
{
    public class GlobalVariable:BaseViewModel
    {
        private static BaseViewModel _selectedViewModel;

        public static BaseViewModel SelectedViewModel
        {
            get { return _selectedViewModel; }
            set { _selectedViewModel = value; }
        }

        private static int check;

        public static int MyCheck
        {
            get { return check; }
            set { check = value; }
        }

        private static UIElement _selectedControl;
        [Browsable(false)]
        public static UIElement SelectedControl
        {
            get { return _selectedControl; }
            set
            {
                _selectedControl = value;

                //OnPropertyChanged("SelectedControl");
            }
        }
    }
}

-------------------------------------------------------------------------------------------
MainWindow.xaml:

<Window x:Class="P1_DataSwitching.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:P1_DataSwitching"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800" WindowState="Maximized">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="40" />
        </Grid.RowDefinitions>
        <Frame Content="{Binding SelectedViewModel}"/>
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" >
            <Button Height="30" Width="60" Content="View1" Command="{Binding SwitchToUC1Command}" />
            <Button Height="30" Width="60" Content="View2" Command="{Binding SwitchToUC2Command}" Margin="50 0 0 0" />
        </StackPanel>
    </Grid>
</Window>

-------------------------------------------------------------------------------------------
MainWindow.xaml.cs:

using P1_DataSwitching.ViewModel;
using System.Windows;

namespace P1_DataSwitching
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }
    }
}

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,557 questions
{count} votes