How to hide one UserControl and open another UserControl inside the Main Window in WPF?

Dmitriy 96 Reputation points
2021-04-09T02:36:04.737+00:00

I am creating a WPF app using the MVVM framework. I have a Main Window which has a grid. Inside that grid I want to display either UserControl1 or UserControl2. The default condition is when the UserControl1 is loaded in the beginning, but after a user clicks on the button Add the current UserControl1 becomes hidden/unloaded (what is the proper term?) and instead of it the UserControl2 becomes open/loaded (?) into the the grid of the Main Window. The same works with the UserControl2. When a user clicks on button Show, the UserControl2 becomes hidden/unloaded and the UserControl1 becomes open/loaded. How would I achieve this in the most simplest way? I was thinking about using TabControl, but unfortunately UserControl1 and UserControl2 are already created as UserControl classes and cannot be redone. For the better picture I created crude wireframes of what I have.

WPF Main Window

86033-wpf-main-window.png

UserControl1

85939-usercontrol1.png

UserControl2

85970-usercontrol2.png

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,705 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,565 questions
{count} votes

2 answers

Sort by: Most helpful
  1. DaisyTian-1203 11,621 Reputation points
    2021-04-12T08:28:51.27+00:00

    I made a simple demo to implement what you want.
    The code for MainWindox.xaml

        <Window.DataContext>  
            <local:ViewModel/>  
        </Window.DataContext>  
        <Grid Name="grid" >  
            <local:MyUC DataContext="{Binding CurrentVM,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />  
        </Grid>  
    

    MyUC is a UserControl and its xaml code is:

     <UserControl.Resources>  
            <DataTemplate DataType="{x:Type local:MyViewModel1}" >  
                <local:UserControl1 DataContext="{Binding}" Visibility="{Binding visibility}"/>  
            </DataTemplate>  
            <DataTemplate DataType="{x:Type local:MyViewModel2}">  
                <local:UserControl2 DataContext="{Binding}" Visibility="{Binding visibility}" />  
            </DataTemplate>  
        </UserControl.Resources>  
        <ContentControl Content="{Binding}" />  
    

    UserControl1.xaml code with adding Visibility="{Binding visibility}" for UserControl1

    <StackPanel>  
                <Label Content="1. UserControl"></Label>  
                <Button Content="Add" Width="120" Height="38" Click="Button_Click1" ></Button>  
       </StackPanel>  
    

    Its cs code is:

     private void Button_Click1(object sender, RoutedEventArgs e)  
            {  
                MyViewModel1 model1 = new MyViewModel1();  
                MyViewModel2 model2 = new MyViewModel2();  
      
                model2.IsShown = true;  
                model2.visibility = Visibility.Visible;  
      
                model1.IsShown = false;  
                model1.visibility = Visibility.Hidden;  
      
                ViewModel viewModel = new ViewModel();  
                viewModel.DataLoad(model1, model2);  
      
                MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;  
                mainWindow.DataContext = viewModel;  
            }  
    

    UserControl2.xaml code with adding Visibility="{Binding visibility}" for UserControl2

    <StackPanel>  
                <Label Content="2. UserControl"></Label>  
                <Button Content="Show" Width="120" Height="38" Click="Button_Click2" ></Button>  
       </StackPanel>  
    

    Its cs code is:

    private void Button_Click2(object sender, RoutedEventArgs e)  
            {  
                MyViewModel1 model1 = new MyViewModel1();  
                MyViewModel2 model2 = new MyViewModel2();  
      
                model2.IsShown = false;  
                model2.visibility = Visibility.Hidden;  
      
                model1.IsShown = true;  
                model1.visibility = Visibility.Visible;  
      
                ViewModel viewModel = new ViewModel();  
                viewModel.DataLoad(model1, model2);  
      
                MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;  
                mainWindow.DataContext = viewModel;  
            }  
    

    Code for C#:

     public class ViewModel : NotifyObject  
        {  
            private object currentVM;  
            public object CurrentVM  
            {  
                get  
                {  
                    return currentVM;  
                }  
                set  
                {  
                    currentVM = value;  
                    OnPropertyChanged("CurrentVM");  
                }  
            }  
      
            MyViewModel1 myView1 = new MyViewModel1();  
      
            MyViewModel2 myView2 = new MyViewModel2();  
      
            public ViewModel()  
            {  
                currentVM = DataLoad(myView1, myView2);  
            }  
      
            public object DataLoad(MyViewModel1 _myView1, MyViewModel2 _myView2)  
            {  
                if (_myView1.IsShown == true && _myView1.visibility == Visibility.Visible) { currentVM = _myView1; }  
                if (_myView2.IsShown == true && _myView2.visibility == Visibility.Visible) { currentVM = _myView2; }  
                OnPropertyChanged("CurrentVM");  
                return currentVM;  
            }  
      
        }  
        public class MyViewModel1 : NotifyObject  
        {  
            public MyViewModel1()  
            {  
                IsShown = true;  
                visibility = Visibility.Visible;  
            }  
      
            private Visibility _visibility;  
            public Visibility visibility  
            {  
                get  
                {  
                    return _visibility;  
                }  
                set  
                {  
                    _visibility = value;  
                    OnPropertyChanged("visibility");  
                }  
            }  
      
            private bool isShown = true;  
            public bool IsShown  
            {  
                get  
                {  
                    return isShown;  
                }  
                set  
                {  
                    isShown = value;  
                    OnPropertyChanged("IsShown");  
                }  
            }  
      
            public string Info1 { get; set; }  
      
        }  
        public class MyViewModel2 : NotifyObject  
        {  
            public MyViewModel2()  
            {  
                IsShown = false;  
                visibility = Visibility.Hidden;  
            }  
            private bool isShown;  
            public bool IsShown  
            {  
                get  
                {  
                    return isShown;  
                }  
                set  
                {  
                    isShown = value;  
                    OnPropertyChanged("IsShown");  
                }  
            }  
            private Visibility _visibility;  
            public Visibility visibility  
            {  
                get  
                {  
                    return _visibility;  
                }  
                set  
                {  
                    _visibility = value;  
                    OnPropertyChanged("visibility");  
                }  
            }  
        }  
        public class NotifyObject : INotifyPropertyChanged  
        {  
            public event PropertyChangedEventHandler PropertyChanged;  
      
            protected void OnPropertyChanged(string propertyName)  
            {  
                if (PropertyChanged != null)  
                {  
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
                }  
            }  
      
        }  
    

    The result is:
    86806-2.gif


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Mouad Cherkaoui 6 Reputation points
    2021-04-12T15:31:05.683+00:00

    Hi,

    there is a good way to deal with this situation "Views as Datatemplates", which consists of making two datatemplates as resources in your view which target the types of the viewmodels for each usercontrol, now in the main view use the content presenter and set its content binding to Binding:

    <Window>
        <Window.Resources>
           <DataTemplate DataType="{x:Type local:userControl1VM}">
              <uc:Control1 />
           </DataTemplate>
    
           <DataTemplate DataType="{x:Type local:userControl2VM}">
              <uc:Control2 />
           </DataTemplate>
        </Window.Resources>
    
        <ContentPresenter Content="{Binding}"/>
    
    </Window>
    

    now depending on the main window datacontext type the data template will change based on its target type.

    0 comments No comments