惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
博客园 - Franky
GbyAI
GbyAI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
IT之家
IT之家
酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recent Announcements
Recent Announcements
Scott Helme
Scott Helme
有赞技术团队
有赞技术团队
M
MIT News - Artificial intelligence
C
CERT Recently Published Vulnerability Notes
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
L
LangChain Blog
L
LINUX DO - 最新话题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Hacker News: Front Page
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
AI
AI
T
Troy Hunt's Blog
Microsoft Azure Blog
Microsoft Azure Blog
阮一峰的网络日志
阮一峰的网络日志
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Vercel News
Vercel News
Microsoft Security Blog
Microsoft Security Blog
罗磊的独立博客
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
博客园 - 叶小钗
人人都是产品经理
人人都是产品经理
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Security @ Cisco Blogs
Cloudbric
Cloudbric
E
Exploit-DB.com RSS Feed
Attack and Defense Labs
Attack and Defense Labs

博客园 - 找事的狐狸

“摸”电脑的时代(三):解析Surface内部结构 “摸”电脑的时代(二):多点触摸秀 写于Silverlight整装待发之际(八):也谈Silverlight人才招聘策略 WinHec扫盲贴 《WPF揭秘》勘误表 如何隐藏UpdatePanel 支付宝实名制实现思路 程序员的必备装备——为健康加油 [好书推荐] C#和.NET 2.0实战:平台、语言与框架 老调重弹——你存储的密码做Hash了吗? JavaScript的世界从来没有像现在这样精彩 CSS实现不同的打印和屏幕显示结果 [翻译] Vista中的音量II: Windows Vista音量种类 文件加密的简单实现(C语言) 如何检测是否安装了.NET 2.0和.NET 3.0 闲话WPF近期发展 WPF实现Tag Cloud 浅析Family Show 2.0的数据结构及基本算法 如何实现一个不规则形状的WPF窗口
浅析Family Show 2.0的子窗体实现
数字游民托尼 · 2007-09-20 · via 博客园 - 找事的狐狸

Family Show的子窗口并不是通过新建模式/非模式窗口实现的,而是通过一些UserControl来实现,例如Welcome窗口、Add a family member窗口,一个窗口就是一个UserControl,如果你想在设计时看到这些窗口的最终效果,建议在Expression Blend里面打开,因为Expression Blend支持在设计时读取动态资源(Dynamic Resources),这要比VS2005的WPF Extension直观许多。

在MainWindow.xaml.cs中,我们可以找到一些以Show和Hidden开头的方法,如ShowDetailsPane、HideDetailsPane、HideFamilyDataControl、HideNewUserControl、ShowNewUserControl、ShowWelcomeScreen、HideWelcomeScreen,这些方法就是用来显示和隐藏用户控件——也就是我们所说的子窗口。以ShowWelcomeScreen和HideWelcomeScreen为例:

        /// <summary>
        
/// Show the Welcome Screen user control and hides the other controls.
        
/// </summary>

        private void ShowWelcomeScreen()
        
{
            HideDetailsPane();
            HideNewUserControl();
            DiagramControl.Visibility 
= Visibility.Hidden;

            WelcomeUserControl.Visibility 
= Visibility.Visible;
        }


        
/// <summary>
        
/// Hides the Welcome Screen.
        
/// </summary>

        private void HideWelcomeScreen()
        
{
            WelcomeUserControl.Visibility 
= Visibility.Hidden;
        }

我们发现,其中除了设置WelcomeUserControl.Visibility为Hidden以外,也对其他不应该显示的用户控件做了隐藏处理。

另外,这些用户控件是直接在Xaml中初始化的,你可以在MainWindow.xaml中找到它们:

      <!-- New User Control -->
      
<local:NewUserControl x:Name="NewUserControl" HorizontalAlignment="Center" VerticalAlignment="Center" AddButtonClick="NewUserControl_AddButtonClick" CloseButtonClick="NewUserControl_CloseButtonClick" />

      
<!-- Welcome User Control -->
      
<local:Welcome x:Name="WelcomeUserControl" HorizontalAlignment="Center" VerticalAlignment="Center" ImportButtonClick="WelcomeUserControl_ImportButtonClick" NewButtonClick="WelcomeUserControl_NewButtonClick" OpenButtonClick="WelcomeUserControl_OpenButtonClick" OpenRecentFileButtonClick="WelcomeUserControl_OpenRecentFileButtonClick" />

      
<!-- Person Info Control -->
      
<local:PersonInfo x:Name="PersonInfoControl" Opacity="0" Visibility="Hidden" CloseButtonClick="PersonInfoControl_CloseButtonClick" />

      
<!-- Family Data Control -->
      
<local:FamilyData x:Name="FamilyDataControl" Opacity="0" Visibility="Hidden" CloseButtonClick="FamilyDataControl_CloseButtonClick" />

这样的声明同时也会在MainWindow.g.cs中生成一个对应的internal变量,如internal Microsoft.FamilyShow.Welcome WelcomeUserControl;,这有点像ASP.NET的aspx中声明asp.net控件(在aspx.cs中也会生成一个对应的控件变量)。

在这段声明中,我们会看到有一些事件的定义,如AddButtonClick、CloseButtonClick等,这些事件其实就是WPF中的路由事件。所谓路由事件是指当事件触发时,触发消息会遍历可视树和逻辑树,这样就可以通知其他父控件或子控件做出适当反应,由于这种事件的最大特点是可以沿着树传递,所以称为路由事件。要定义路由事件,必须提供一个公共的事件属性,如WelcomeUserControl的OpenButtonClick就是一个典型事件属性,我们来看看它的定义:

        // Expose this event for this control's container
        public event RoutedEventHandler OpenButtonClick
        
{
            add 
{ AddHandler(OpenButtonClickEvent, value); }
            remove 
{ RemoveHandler(OpenButtonClickEvent, value); }
        }

但仅有这样一个属性是不够的,还要有一个注册动作,告诉WPF的事件管理器这是一个路由事件:

        public static readonly RoutedEvent OpenButtonClickEvent = EventManager.RegisterRoutedEvent(
            
"OpenButtonClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Welcome));

这里的参数中指定路由策略为Bubble,即冒泡,具体的有关路由策略的区别,大家可以去看《WPF Unleashed》里面有详细的讲解;这里的第一个参数name被指定为OpenButtonClick,就是我们刚才定义的那个事件属性的名称,但请注意,这个参数的值可以与刚才指定的事件属性不同,只是一个key而已。到目前为止,我们并没有指定由哪个控件来触发这个路由事件,所以就有了下面的代码:

        private void OpenButton_Click(object sender, RoutedEventArgs e)
        
{
            RaiseEvent(
new RoutedEventArgs(OpenButtonClickEvent));
        }

这就是负责触发事件的代码,这里的OpenButton_Click对应于Welcome用户控件中的Open按钮的Click事件。所以大家以后写WPF程序,可以考虑参考family show的程序模型,采用User Control而非Window来开发应用程序,这样就不需要考虑窗口间的交互问题,因为从头到尾都是在一个窗口中进行处理。而对于那些Flash的开发人员来说,这种模式更是熟悉不过了,你可以把User Control理解成MovieClip对象。

下面我们来看看子窗口的构成,

Welcome用户控件

NewUserControl用户控件

WPF从发布之初就一直在强调UI的设计,Family Show的窗口就很好的体现了这一点,当然我说这句话绝对不是因为这些窗口漂亮,而是因为这样的窗口设计越来越像网页设计,我们以Welcome用户控件为例,做一些分析:

在这张图中,整个窗口被分成了三部分:Header、Content和Footer,整个窗口被放置在一个StackPanel中,其中的三部分都是由一个Border作为容器控件。Footer的实现最简单,Border控件中仅放了一个Label控件;Header的Border中放了一个Grid,其中的Welcome文本则是一个TextBlock控件,至于后面的图则是一个Rectangle控件(用动态资源WelcomeHeaderBg作为Fill的值,这个动态资源其实就是一个DrawingBrush,所以可以赋给Rectangle.Fill);Content的实现相对复杂些,其中也用了一个Grid用于布局,三个按钮New、Open、Import则放在一个StackPanel中,那条灰色的水平线是一个GridSplitter,Open Recent其实是一个Label控件,其实在OpenRecent下面还有一个StackPanel控件,用来放最近打开的文件列表的,由于文件列表是通过代码生成的,所以这里看不到有任何数据。(如果你在Expression Blend中看这个用户控件会一目了然,在Object and Timeline窗口中有一个树型视图,可以方便地了解布局控件的包含关系。)

从这个窗口的布局来看,大家是不是觉得越来越有网页设计的味道的,WPF中的style其实就是从css引进过来的,虽然功能上比css强大很多,但这个概念绝对是一种借鉴,从这一点来看,WPF正在改变一种观念,未来的用户界面设计将越来越方便,我们不再需要一些第三方的skin机制来实现友好且漂亮的界面,直接用WPF就可以搞定了,当然这种理念对于过去开发WinForm的人来说可能过于时尚了,要让大量的开发人员接受这种理念还需要相当长的一段时间。