Is it possible to load user controls on demand?

jennyliu835 221 Reputation points
2020-09-25T01:03:05.737+00:00

Hi Peter + Daisy,

Suppose more user controls will be added in the future, is it possible to load them without having to change the LoadListOfUserControls() or List<UserControl> usersList = new List<UserControl>(){...}? In another words, just adding some user controls under the folder "UserControls"and change the following line
int _num = new Random().Next(1,7);
to:
int _num = new Random().Next(1,10);
or
int _num = new Random().Next(1,18);
and so forth.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,710 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,316 Reputation points
    2020-09-25T03:31:36.487+00:00

    Hi Jenny,
    you can include UserControls in XAML files (ResourceDictionary) and load this files on demand into List of UserControls. If you want to use random for selecting after loading files you can use List.Count like this:

    int _num = new Random().Next(0,ListOfUserControls,Count);

    Try following demo:

    ViewModel:

    using System;  
    using System.Collections;  
    using System.Collections.Generic;  
    using System.ComponentModel;  
    using System.IO;  
    using System.Runtime.CompilerServices;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Input;  
    using System.Windows.Markup;  
      
    namespace WpfApp2  
    {  
      public class ViewModel : ICommand, INotifyPropertyChanged  
      {  
        public ViewModel()  
        {  
          LoadListOfUserControls();  
        }  
        public Dictionary<string, UserControl> ListOfControls { get; set; }  
        private void LoadListOfUserControls()  
        {  
          ListOfControls = new Dictionary<string, UserControl>();  
          foreach (var fi in Directory.GetFiles(@"UCResources"))  
          {  
            var dict = (ResourceDictionary)XamlReader.Load(new FileStream(fi, FileMode.Open));  
            foreach (DictionaryEntry item in dict)  
            {  
              var uc = item.Value as UserControl;  
              if (uc != null) ListOfControls.Add(item.Key.ToString(), uc);  
            }  
          }  
        }  
      
        private UserControl _actualUserControl = null;  
        public UserControl ActualUserControl  
        {  
          get => this._actualUserControl;  
          set { this._actualUserControl = value; OnPropertyChanged(); }  
        }  
      
        public void Execute(object parameter) =>  
          ActualUserControl = ((KeyValuePair<string, UserControl>)parameter).Value;  
      
        public event EventHandler CanExecuteChanged;  
        public bool CanExecute(object parameter) => true;  
      
        public event PropertyChangedEventHandler PropertyChanged;  
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "") =>  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
      }  
    }  
    

    XAML:

    <Window x:Class="WpfApp2.MainWindow"  
            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:WpfApp2"  
            mc:Ignorable="d"  
            Title="MainWindow"  Height="558" Width="718" Background="AliceBlue">  
      <Window.Resources>  
        <local:ViewModel x:Key="vm"/>  
      </Window.Resources>  
      <Grid DataContext="{StaticResource vm}">  
        <Menu Name="menu1" Width="343" Margin="76,110,0,0"   
              HorizontalAlignment="Left" VerticalAlignment="Top"  
              FontFamily="Times New Roman" FontSize="20"   
              Background="#FF00F500"  
              ItemsSource="{Binding ListOfControls}">  
          <Menu.ItemContainerStyle>  
            <Style TargetType="MenuItem">  
              <Setter Property="Header" Value="{Binding Key}" />  
              <Setter Property="Command" Value="{Binding Source={StaticResource vm}}" />  
              <Setter Property="CommandParameter" Value="{Binding}" />  
            </Style>  
          </Menu.ItemContainerStyle>  
        </Menu>  
        <UserControl Height="190" Width="490" Margin="74,184,118,133"   
                     Background="Aqua">  
          <Grid Name="grid2" Height="185" Width="485"   
                Background="#FFFDD293">  
            <TextBlock Name="textBlock1"   
                       Text="User Control Area"  
                       Height="30" Width="180"   
                       HorizontalAlignment="Left" VerticalAlignment="Top"  
                       FontFamily="Times New Roman" FontSize="22"     
                       Background="#FFFFCD00"/>  
            <ContentControl Content="{Binding ActualUserControl}"/>  
          </Grid>  
        </UserControl>  
      </Grid>  
    </Window>  
    

    UserControls are included in ResourceDictionary in SubFold "UCResources" like this:

    <ResourceDictionary 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">  
      <UserControl x:Key="UC1">  
        <Grid>  
          <TextBlock Text="User Control 1" TextWrapping="Wrap"  
                     Height="28" Width="142" Margin="66,102,0,0"  
                     HorizontalAlignment="Left" VerticalAlignment="Top"    
                     Background="#FF97E3F3"/>  
        </Grid>  
      </UserControl>  
      <UserControl x:Key="UC2">  
        <Grid>  
          <TextBlock Text="User Control 2" TextWrapping="Wrap"  
                     Height="28" Width="142" Margin="66,102,0,0"  
                     HorizontalAlignment="Left" VerticalAlignment="Top"    
                     Background="#FFB2E68F"/>  
        </Grid>  
      </UserControl>  
    </ResourceDictionary>  
    

    28262-x.png


0 additional answers

Sort by: Most helpful