为什么WPF会在添加到TabControl后立即为视图触发Loaded事件?

时间:2016-12-07 09:29:01

标签: c# wpf xaml

我有一个简单的C#WPF应用程序,如下所示:

enter image description here

我以编程方式添加了Item2,我想知道为什么Loaded事件在被添加到TabControl之后不久被触发,然后在我打开它时再次触发。

MainWindow.xaml的代码如下所示:

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

它的代码隐藏是:

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);
        }
    }
}

如您所见,我有一个名为Control1的控件,另一个名为Control2。它们使用以下MyControl.xaml文件定义:

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

以下代码隐藏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";
    }
}

当我打开应用程序时,我得到以下控制台输出:

Loaded Control1
Loaded Control2

当我切换到Item2时:

Unloaded Control1
Loaded Control2

回到第1项:

Unloaded Control2
Loaded Control1

后两者有意义;当我从控件导航时,它会在新控件加载时被卸载。

但是,在显示Control2之前,我不明白为什么最初会加载Control2。这会导致Control2在获得Loaded事件之前连续收到两个Unloaded个事件。

1 个答案:

答案 0 :(得分:0)

当我们明确添加标签项时,每个标签项都会立即加载并初始化,包含所有内容。(有关详细信息,请参阅此主题Lazy loading WPF tab content