wpfxamlvisual-studio-designer

Xaml: design a layout with dynamically visible components


In a mvvm application some areas inside a window (in reality it is a UserControl inside MainWindow) are dynamically displayed according to the user selections.

The changing blocks are inside Stackpanels, I have 4 of them and only one at a time is displayed. This is accomplished binding Visibility to a bool property and using the BooleanToVisibilityConverter.

I put all the alternate StackPanel inside parent control. It works correctly, but during design phase in Visual Studio I see all of them, so I have problems in figuring the final layout.

How can I easily create the layout having more controls which share the same window area and are displayed one at a time ?


Solution

  • Setting A Design Time Only Data Context

    Developing XAML in the Studio Designer can be greatly simplified by setting the Design-Time Data Context.

    One implementation is based on setting a duplicate DataContext which will be ignored during the final compilation.

    To implement the switching, add to the ViewModel, a property that will inform the designer whether it can be used in Development Mode or not.


    I use an MVVMLight situation for this example, but for this declared instance property IsInDesignMode and static property ViewModelBase.IsInDesignModeStatic.

    Example:

    using System.ComponentModel;
    
    namespace DataContextDesignTime.Example
    {
        public class MyViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private bool _flag;
            public bool Flag
            {
                get => _flag;
                set
                {
                    if (!Equals(_flag, value))
                    {
                        _flag = value;
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Flag)));
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NotFlag)));
                    }
                }
            }
    
            public bool NotFlag => !Flag;
        }
    }
    
    <Window x:Class="DataContextDesignTime.Example.ExamleWindow"
            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:DataContextDesignTime.Example"
            mc:Ignorable="d"
            Title="ExamleWindow" Height="450" Width="800">
        <d:Window.DataContext>
            <local:MyViewModel Flag="True" NotFlag="True"/>
        </d:Window.DataContext>
        <Window.Resources>
            <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        </Window.Resources>
        <StackPanel>
            <Border Background="LightBlue" Height="200"
                    Visibility="{Binding Flag, Converter={StaticResource BooleanToVisibilityConverter}}"/>
            <Border Background="LightGreen" Height="400"
                    Visibility="{Binding NotFlag, Converter={StaticResource BooleanToVisibilityConverter}}"/>
        </StackPanel>
    </Window>
    

    In this example, you can change property values in XAML or in the Property Browser.
    And you will immediately see the work of your bindings, triggers, how the display for certain data changes.


    enter image description here


    Note

    This may fail on more complex VMs/packages, but in general by setting the DataContext at design time is not difficult.

    I need to recompile the project to see the changes in the properties.

    The XAML Designer panel has an «Enable/Disable Project Code» button. enter image description here