0

I have a simple C# WPF application looking like this:

enter image description here

I'm adding Item2 programmatically, and I wonder why the Loaded event is fired both shortly after it has been added to the TabControl and then again when I open it.

The code for my MainWindow.xaml looks as follows:

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TabControl Name="MyTabControl" >
            <TabItem Name="Item1" Header="Item1">
                <local:Control1 />
            </TabItem>
        </TabControl>
    </Grid>
</Window>

And its code-behind is:

using System.Windows;
using System.Windows.Controls;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            var item = new TabItem
            {
                Content = new Control2(),
                Header = "Item2"
            };
            MyTabControl.Items.Add(item);
        }
    }
}

As you can see, I have one control called Control1 and another called Control2. They are defined with the following MyControl.xaml file:

<UserControl x:Class="WpfApplication1.MyControl"
             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" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>

    </Grid>
</UserControl>

And the following code-behind MyControl.xaml.cs:

using System.Diagnostics;

namespace WpfApplication1
{
    public abstract partial class MyControl
    {
        protected abstract string MyName { get; }

        protected MyControl()
        {
            InitializeComponent();
            Loaded += (sender, args) => Debug.Print("Loaded {0}", MyName);
            Unloaded += (sender, args) => Debug.Print("Unloaded {0}", MyName);
        }
    }

    public class Control1 : MyControl
    {
        protected override string MyName => "Control1";
    }

    public class Control2 : MyControl
    {
        protected override string MyName => "Control2";
    }
}

When I open the application, I get the following console output:

Loaded Control1
Loaded Control2

And when I switch to Item2:

Unloaded Control1
Loaded Control2

And back to Item1:

Unloaded Control2
Loaded Control1

The latter two make sense; when I navigate from a control it gets unloaded while the new control gets loaded.

However, I don't understand why Control2 is loaded initially, before it has been shown. This causes Control2 to receive two Loaded events in a row, before it gets an Unloaded event.

Daniel Jonsson
  • 3,261
  • 5
  • 45
  • 66

1 Answers1

0

When we add Tab Items explicitly, each tab item is loaded and initialized immediately containing everything.(Please refer to this topic for more details Lazy loading WPF tab content)

Community
  • 1
  • 1
NTinkicht
  • 972
  • 2
  • 12
  • 34