Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You only have 2 things wrong with this code.</p> <p><strong>1) You can't set the visibility of a usercontrol directly... you have to set it on a container:</strong></p> <pre><code>&lt;Grid Visibility="Collapsed"&gt; &lt;myControls:MyUserControl /&gt; &lt;/Grid&gt; </code></pre> <p><strong>2) Visibility is not a boolean value, it is an enum. As such, you will need to use a converter to convert from boolean to Visibility. Observe:</strong></p> <pre><code>&lt;Window ...&gt; &lt;Window.Resources&gt; &lt;BooleanToVisibilityConverter x:Key="BoolToVis" /&gt; &lt;/Window.Resources&gt; &lt;Grid Visibility="{Binding ShouldShowUsercontrol1, Converter={StaticResource BoolToVis}}"&gt; &lt;myControls:MyUserControl /&gt; &lt;/Grid&gt; &lt;/Window&gt; </code></pre> <p>That should be it. Hope this helps.</p> <p>There are other things that you are leaving clues about that might affect the ability of this to work. For example, you don't show the biggest container element... are you wrapping everything in a StackPanel? If you are wrapping everything in a Grid, for example, the controls will overlay everything in layers.</p> <p>Try these changes I suggest... it should get you closer.</p> <hr> <p><strong>Edit: Another idea using data templates</strong></p> <p>Another thing you could do is make sure you have a unique ViewModel for each of these views you want to show and hide:</p> <pre><code>public class MyFirstViewModel : ViewModel { } public class MySecondViewModel : ViewModel { } </code></pre> <p>Then from your "parent" or "main" ViewModel, you show or hide the views you want by virtue of having them in a collection of ViewModels:</p> <pre><code>public MyMainViewModel : ViewModel { public ObservableCollection&lt;ViewModel&gt; ViewsToShow { ... } public void ShowFirstViewModel() { ViewsToShow.Add(new MyFirstViewModel()); } } </code></pre> <p>To wire everything up in your view, you would then datatemplate these types with their user controls (but this would not cause those views to be instantiated unless they were needed:</p> <pre><code>&lt;Window ...&gt; &lt;Window.Resources&gt; &lt;DataTemplate DataType="{x:Type myViewModels:MyFirstViewModel}"&gt; &lt;myViews:MyFirstView /&gt; &lt;/DataTemplate&gt; &lt;DataTemplate DataType="{x:Type myViewModels:MySecondViewModel}"&gt; &lt;myViews:MySecondView /&gt; &lt;/DataTemplate&gt; &lt;/Window.Resources&gt; &lt;ItemsControl ItemsSource="{Binding ViewsToShow}" /&gt; &lt;/Window&gt; </code></pre> <p>And for any ViewModels you put in "ViewsToShow", the view will automatically see that and template in the appropriate view. Again, without instantiating it before it's needed.</p> <p>This is probably a little cleaner than putting everything single thing in the View and setting visibility, but it would be dependent on you have a unique view model type for every view, which might not be the case.</p> <hr> <p>The question of saving state comes up when using the DataTemplated approach. The solution here is to tread your ViewModel as the state of the control and design both your ViewModels and your Views accordingly. Here is an example that allows you to swap out your Views using DataTemplating, but switching back and forth saves state.</p> <p>Assume you have the setup from the last section w/ 2 viewmodels that have datatemplates defined. Let's change up the MainViewModel a little:</p> <pre><code>public MyMainViewModel : ViewModel { public RelayCommand SwapViewsCommand { ... } public ViewModel View { ... } private ViewModel _hiddenView; public MyMainViewModel() { View = new MyFirstViewModel(); _hiddenView = new MySecondViewModel(); SwapViewsCommand = new RelayCommand(SwapViewModels); } public void SwapViewModels() { var hidden = _hiddenView; _hiddenView = View; View = hidden; } } </code></pre> <p>And a few changes to the main view. I've omitted the DataTemplates for brevity.</p> <pre><code>&lt;Window ...&gt; &lt;!-- DataTemplates Here --&gt; &lt;Button Command="{Binding SwapViewsCommand}"&gt;Swap!&lt;/Button&gt; &lt;ContentControl Content="{Binding View}" /&gt; &lt;/Window&gt; </code></pre> <p>That's it. The secret here is I'm saving the reference to the original view model. This way, let's say there is a string property in a viewmodel and an associated textbox in the DataTemplated usercontrol with a <strong>two-way binding</strong> then the state will essentially be saved.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload