question

Dmitriy-2994 avatar image
0 Votes"
Dmitriy-2994 asked DaisyTian-1203 commented

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

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


dotnet-csharpwindows-wpf
usercontrol1.png (3.3 KiB)
usercontrol2.png (5.7 KiB)
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@Dmitriy-2994
Did you create your Usercontrol with C# code not XAML?If you did it, how about setting this.SetBinding(UserControl.VisibilityProperty, new Binding("visibility")); in the UserControl class and create visibility which implement INotifyPropertyChanged in its Viewmodel to control Visibility?

0 Votes 0 ·

I am not sure what do you mean. I have both: UserControl1.xaml and UserControl1.xaml.ca. The same is true for UserControl2. Right now in my Main Window I am instantiating UserControl1 through this:

<Grid x:Name="grdMainAppWindow">
<local:UserControl1></local:UserControl1>
</Grid>

0 Votes 0 ·

@Dmitriy-2994
Did you check my answer? If you did, could you let me know if it works for you or not? If it doesn't work for you, please let me know and give me more info to analyze.

0 Votes 0 ·
DaisyTian-1203 avatar image
0 Votes"
DaisyTian-1203 answered

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.


2.gif (16.2 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

mouadcherkaoui avatar image
0 Votes"
mouadcherkaoui answered

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.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.