Search code examples
c#wpfbindingdatacontextresourcedictionary

Conditional Resources Creation WPF XAML Design / Run time


Following a first question on WPF Cascading Binding,

I remarked that I had more Resources than desired defined in both the MainWindow and the UserControls:

This is well seen in Snoop

bindingMCVE snoop view

  • the MainWindow XAML has an "instance" of a MainWindow ViewModel that paints the 2 usercontrol in green and blue

Test application of 2 UserControls

  • additionnaly there are 2 instances of usercontrol viewmodels for each of the 2 UserControls that would paint the inner circle in red

simple usercontrol

  1. My first Intention in the Usercontrol was to be able to see "live" how my control would look like ( I painted it red to distinguish this "model" from the green and blue circles in the Main Window)
  2. My Resources are very cheap to create, so no matter if I have 2 extra resources that are still living in my application, but I would anticipate the time where my Resources will be more expensive...

Finally my question is :

How can I conditionnaly let Resources be created in "low level" control ( so that I can have a preview in the view of the control ) but prevent this creation when running the full application ( or the view of the Main Window ) because I will bind to the Resources of this upper level.

Many thanks in advance.

Best Regards.

NGI


Solution

  • I will finally try to answer my own question

    Result is as awaited no "duplicate resources" in the lower level ViewModel instances The result in snoop: Snoop view. Only the mainwindow viewmodel instance

    The XAML code

    <UserControl x:Class="BindingMCVE.UserControl1"
             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:BindingMCVE"
             d:DataContext="{d:DesignInstance {x:Type vm_nmspc:my_usercontrol_vm}, IsDesignTimeCreatable=True}"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="100"
             xmlns:vm_nmspc="clr-namespace:BindingMCVE.ViewModel"               
     >
    
    <UserControl.Resources>
        <!--No resources created in XAML-->
    </UserControl.Resources>
    
    
            <Grid>
        <StackPanel  Height="100"  Width="100">
            <Ellipse  Fill="{Binding my_color}" Height="50" Width="50" />
        </StackPanel>
        
    </Grid>
    

    Note the new line:

    d:DataContext="{d:DesignInstance {x:Type vm_nmspc:my_usercontrol_vm}, IsDesignTimeCreatable=True}"

    And there is absolutely no other modifications !!

    The trick is to use the IDE to support you ( if you are unaware of the syntax that should be used in the XAML ).

    I will try to illustrate what I did.

    Choose your object, and in the format menu choose Set Design Time DataContext

    Set Design Time DataContext

    Then choose your DesignInstance ( here the ViewModel my_usercontrol_vm) and do not forget to tick IsDesignTimeCreatable

    enter image description here

    This created the magic line in the Ellipse declaration but I moved it on the top of the XAML.

    So this answered my question. It is possible with no deep knowledge on WPF/XAML to make all your subviews (controls) "rendered" without the additional cost of wasted resources of viewmodels

    To give echo to what Maximus gave in the first answer, I found also another post (will try to find it again and quote it in a next edit) using directly the function DesignerProperties.GetIsInDesignMode( )

    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
    
            InitializeComponent();
    
            if (  DesignerProperties.GetIsInDesignMode(this))
            {
                //Do what you want here for design time specific actions
            }
        }
    }