Search code examples
c#wpfxamlresourcedictionary

Load ResourceDictionary item dynamically based on property value


Is it possible to load one of my stackpanels based on a string property inside my viewmodel? So if string is MyStackPanel1 then the appropiate stackpanel will be injected into the grid of my mainwindow.

My ResourceDictionary

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">


    <StackPanel x:Key="MyStackPanel1" Background="{Binding Color}"> 
       // Has some content     
    </StackPanel>

    <StackPanel x:Key="MyStackPanel2" Background="{Binding Color}">   
     // Has some other content
    </StackPanel>
</ResourceDictionary>

My MainWindow:

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Dictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>

    </Grid>
</Window>

Here an idea of the viewmodel:

public class ViewModel : INotifyPropertyChanged {
  public event PropertyChangedEventHandler PropertyChanged;
  public string StackPanelName { get; set; };
  public string Color { get; set; };

   private void ChangedHandler(string propertyToBeChanged) {

   }
}

Solution

  • You could use a ContentControl with ContentTemplates but for the bindings to work you should set the Content property of the ContentControl:

    <Window.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="MyResource1" x:Shared="false">
                <StackPanel>
                    <TextBlock Background="{Binding background}">Hello World</TextBlock>
                </StackPanel>
            </DataTemplate>
    
            <!-- Resource2 and so on -->
        </ResourceDictionary>
    </Window.Resources>
    
    <Grid x:Name="Body">
        <!-- "background" is a property of the view model -->
        <ContentControl x:Name="Sample" Content="{Binding}" ContentTemplate="{StaticResource MyResource1}"/>
    </Grid>