What is a more effective way to load a number of user controls?

asked 2020-09-23T05:47:28.657+00:00
jennyliu835 221 Reputation points

Hi Peter + Daisy,
It seems that "Swich" can be used for several user controls (Here is my initial coding), but it is certainly not a good solution when the number goes up. So what is a more effective way to load a number of user controls?
Thanks

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,170 questions
No comments
{count} votes

Accepted answer
  1. answered 2020-09-24T05:11:06.517+00:00
    Peter Fleischer (Freelancer) 17,396 Reputation points

    Hi Jenny,
    another approach can be this code:

    using System;
    using System.Collections.Generic;
    using System.Windows;
    using System.Windows.Controls;
    using WpfApp2.UserControls;
    
    namespace WpfApp2
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
          LoadListOfUserControls();
        }
    
        private Dictionary<int, UserControl> list;
        private void LoadListOfUserControls()
        {
          list = new Dictionary<int, UserControl>();
          list.Add(1, new UserControl1());
          list.Add(2, new UserControl2());
          list.Add(3, new UserControl3());
          list.Add(4, new UserControl4());
          list.Add(5, new UserControl5());
          list.Add(6, new UserControl6());
        }
    
        private void MenuItem_Click(object sender, RoutedEventArgs e)
    
        {
          int _num = new Random().Next(1,7);
    
          grid2.Children.Clear();
          grid2.Children.Add(list[_num]);
        }
      }
    }
    
    No comments

3 additional answers

Sort by: Most helpful
  1. answered 2020-09-24T01:59:47.99+00:00
    DaisyTian-1203 11,506 Reputation points

    How about using list to add UserControls then load them one by one. I make a workaround base on making some change in your demo for you in bleow:

            List<UserControl> usersList = new List<UserControl>() { new UserControl1(), new UserControl2(), new UserControl3(), new UserControl4()};  
            int m = new Random().Next(4);  
            private void MenuItem_Click(object sender, RoutedEventArgs e)  
            {  
                if(m<usersList.Count)  
                {  
                    grid2.Children.Clear();  
                    grid2.Children.Add(usersList[m]);  
                    m ++;  
                }else if(m== usersList.Count)  
                {  
                    m = 0;  
                }  
            }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  2. answered 2020-09-24T05:47:39.827+00:00
    Peter Fleischer (Freelancer) 17,396 Reputation points

    Hi Jenny,
    another MVVM approach can be this code:

    <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>  
    

    And ViewModel:

    27834-x.png

    Buggy forum software don't show code, see attached file 27850-x.txt.

    Result:

    27942-x.gif


  3. answered 2020-09-25T09:56:15.297+00:00
    Andy ONeill 361 Reputation points

    It is bad practice to include any instance of a control in a viewmodel.
    This is a black vs white area.
    Freezables are arguably in a grey area but any uielement is not.

    You should instead use datatemplating or instantiating the usercontrol in the view.
    Although not aimed at this particular topic, you can see a quick and dirty version here:

    https://social.technet.microsoft.com/wiki/contents/articles/52485.wpf-tips-and-tricks-using-contentcontrol-instead-of-frame-and-page-for-navigation.aspx

    This uses types to avoid the viewmodel instantiating UI.
    The reason best practice insists viewmodels do not reference UI directly is twofold:

    1) Separation of concerns.
    The viewmodel here only "knows" about a viewmodel type.
    If you decide later to change the view to some other then this is "just" a change in your resources associate datatemplate with viewmodel type.

    2) Testability
    When you instantiate any UI control this introduces an overhead and the possibility you will slip into working with UI events and suchlike in your viewmodels.
    If you have no UI instance at all then you can't do that and your lead will be happier as he does your code reviews.