关于WP7 中页面元素生成 加载顺序的简单分析
2011-12-15 08:57 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 条所讲的顺序。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步