代码改变世界

关于WP7 中页面元素生成 加载顺序的简单分析

  F-sea  阅读(418)  评论(1编辑  收藏  举报

在写代码时 我们通常会关系 页面中各个控件的加载顺序,现在我们来做一个简单分析 

我们先创建一个WP 应用程序  Phone App2  

我们先重写 3个控件 Grid、StackPlane、Button 并在构造函数中添加输出一条debug 信息

public class CustomGrid : System.Windows.Controls.Grid
    {
        public CustomGrid()
            :base()
        {
            System.Diagnostics.Debug.WriteLine("Structure Grid");
        }
 
       
    }
 
    public class CustomStackPanel: System.Windows.Controls.StackPanel
    {
        public CustomStackPanel()
            : base()
        {
            System.Diagnostics.Debug.WriteLine("Structure StackPanel");
             
             
 
        }
 
 
    }
 
 
    public class CustomButton:Button
    {
        public CustomButton()
            : base()
        {
            System.Diagnostics.Debug.WriteLine("Structure Button");
 
        }
    }

  


然后我们在MainPage 中添加如下界面布局 ,大家注意到  这个布局是用的是我们刚才定制的空间 并且 这是一个嵌套的布局

<c:CustomGrid x:Name="LayoutRoot" Background="Transparent" Loaded="LayoutRoot_Loaded" Unloaded="LayoutRoot_Unloaded">
        <c:CustomStackPanel x:Name="panle" Loaded="StackPanel_Loaded" Unloaded="CustomStackPanel_Unloaded">
 
            <c:CustomButton x:Name="button" Content="Button" Loaded="CustomButton_Loaded" Unloaded="CustomButton_Unloaded" Click="button_Click"></c:CustomButton>
        </c:CustomStackPanel>
    </c:CustomGrid>

  


接下来我们 分别为这3个控件 写loaded 和 unloaded 方法 同样在里面输出一条 Debug信息

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Page Loaded");
 
        }
 
        private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("LayoutRoot Loaded");
 
        }
 
        private void StackPanel_Loaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Panle Loaded");
 
        }
 
        private void CustomButton_Loaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("button Loaded");
 
        }
 
        private void PhoneApplicationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Page UnLoaded");
 
        }
 
        private void LayoutRoot_Unloaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("LayoutRoot UnLoaded");
 
        }
 
        private void CustomStackPanel_Unloaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Panle UnLoaded");
 
        }
 
        private void CustomButton_Unloaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("button UnLoaded");
 
        }

  


重写 Nav To 和  Nav From  在里面输出debug 信息

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Nav From");
 
            base.OnNavigatedFrom(e);
        }
 
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("Nav To");
 
            base.OnNavigatedTo(e);
        }

  

在页面构造函数中添加如下代码

public MainPage()
        {
            if (this.LayoutRoot == null)
            {
                System.Diagnostics.Debug.WriteLine("LayoutRoot null");
 
            }
 
            if (this.panle == null)
            {
                System.Diagnostics.Debug.WriteLine("panle null");
 
            }
 
            if (this.button == null)
            {
                System.Diagnostics.Debug.WriteLine("button null");
 
            }
 
            InitializeComponent();
 
            if (this.LayoutRoot != null)
            {
                System.Diagnostics.Debug.WriteLine("LayoutRoot not null");
                 
            }
 
            if (this.panle != null)
            {
                System.Diagnostics.Debug.WriteLine("panle not null");
 
            }
 
            if (this.button != null)
            {
                System.Diagnostics.Debug.WriteLine("button not null");
 
            }
 
            //tb.InputScope= new InputScope();
            //tb.InputScope.
        }

  

最后我们给button 一个 Onclick 事件 让他 nav 到 一个新的页面去

private void button_Click(object sender, RoutedEventArgs e)
     {
         this.NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
     }

  

好了  现在我们把 MainPage 中的各个控件 在页面 开始构造就不停的输出信息

我们现在运行程序 然后点击 button  应用页面被nav到了 page1 然后点击 back 后退 在点击后退 退出应用 
输出结果如下: 

'UI Task' (Managed): Loaded 'mscorlib.dll'
'UI Task' (Managed): Loaded 'System.Windows.RuntimeHost.dll'
'UI Task' (Managed): Loaded 'System.dll'
'UI Task' (Managed): Loaded 'System.Windows.dll'
'UI Task' (Managed): Loaded 'System.Net.dll'
'UI Task' (Managed): Loaded 'System.Core.dll'
'UI Task' (Managed): Loaded 'System.Xml.dll'
'UI Task' (Managed): Loaded '\Applications\Install\13445E7F-EE4A-4183-8D33-EED4D9CF7EA2\Install\PhoneApp1.dll', Symbols loaded.
'UI Task' (Managed): Loaded 'Microsoft.Phone.dll'
'UI Task' (Managed): Loaded 'Microsoft.Phone.Interop.dll'
LayoutRoot null
panle null
button null
Structure Grid
Structure StackPanel
Structure Button
LayoutRoot not null
panle not null
button not null
Nav To
button Loaded
Panle Loaded
LayoutRoot Loaded
Page Loaded
Nav From
'UI Task' (Managed): Loaded 'System.Runtime.Serialization.dll'
Page UnLoaded
LayoutRoot UnLoaded
Panle UnLoaded
button UnLoaded
Nav To
button Loaded
Panle Loaded
LayoutRoot Loaded
Page Loaded
Nav From
The thread '<No Name>' (0x1b3020e) has exited with code 0 (0x0).
The thread '<No Name>' (0xe13008a) has exited with code 0 (0x0).
The thread '<No Name>' (0xf820096) has exited with code 0 (0x0).
The program '[260440182] UI Task: Managed' has exited with code 0 (0x0).

  



现在来分析下: 
在应用启动进入 mainpage 时 开始执行 mainpage 的构造函数  在执行InitializeComponent(); 前 页面中的个个组件全部都是Null , 然后我们看到 各个页面中各个控件开始构造 然后 InitializeComponent(); 接触 各个空间 检查都不为null , 注意 控件 构造顺序: LayoutRoot》StackPanle》Button 这是一个从下层到上层的顺序 这个我们先记下 。 然后 MainPage 开始 执行 重写的 Nav To 方法  接着 是各个组件 报告 Loaded  而 Loaded 的顺序是 button > Panle> LayoutRoot > Page  这是一个从上层到下层的顺序 
Start:

LayoutRoot null
panle null
button null
Structure Grid
Structure StackPanel
Structure Button
LayoutRoot not null
panle not null
button not null
Nav To
button Loaded
Panle Loaded
LayoutRoot Loaded
Page Loaded

  



接下来我们单击了 button 开始导航到一个新的页面 Page1  debug 信息告诉我们  Page 先执行了 重写的Nav From 然后 各个空间开始 报告 unloaded 顺序是page>LayoutRoot>panle>button

Nav From:

Nav From
Page UnLoaded
LayoutRoot UnLoaded
Panle UnLoaded
button UnLoaded

  




接下来 我们从 Page1 返回到 MainPage debug 信息告诉我们  Page 先执行了 重写的Nav To 然后 各个空间开始 报告 loaded 顺序与之前相同是
button > Panle> LayoutRoot > Page

Nav Back :

Nav To
button Loaded
Panle Loaded
LayoutRoot Loaded
Page Loaded





根据上面的结果我们来做个简单的分析
1、当页面开始 开始加载 在首先是构造页面 这是后 页面中的各个元素还没有开始创建(都是 Null )
2、在 构造函数中的InitializeComponent(); 他将去分析 xaml 布局文件 并且初始化各个逐渐 初始顺序从下层往上层 (这个顺序应该和 xaml 中各个空间所写的位置 有关系 当然这也要看 微软对 xaml 的解析方式,当然这只是猜测 我还没对此做过测试 也没看到相关的描述文档  )
现在我们 假设有个 栈来储存这个控件 ,空间被初始化后 一个一个压入栈最底层控件在栈底 上层控件在栈顶。(不能确定是否正确)
3、构造结束后页面开始执行Nav To 方法
4、Nav To 方法后页面是 Loaded 方法, 注意 Loaded 的执行顺序 是从上层控件 开始 到底层控件结束 
可以认为是 栈中的控件被读出并执行Load 那么先出栈的就应该是上层控件 最后是底层控件(不能确定是否正确)
5、当页面被 Nav 到 新的页面之前 页面先执行了 Nav From  方法 然后开始 UnLoad 控件 执行顺序是 从底层控件开始 到上层控件结束
可以认为是在 load 是控件被读出栈 并被放入一个新的栈 这样的话 上层的空间在栈底  下层控件在栈顶  在unload 时 读取栈 并unload 那么先出栈的应该是 下层控件 最后是上层控件 
6、注意 这是后 页面没有被销毁  只是页面实体对象被压入了 NavigationService.BackStack 
7、当从 新页面后退是 新的页面被销毁, backatack 顶部的对象将成为当前页面 这时候的执行顺序 将是  3、4 条所讲的顺序。

努力加载评论中...
点击右上角即可分享
微信分享提示