1.1 WPF简介
WPF的全称是Windows Presentation Foundation,是微软新发布的Vista操作系统的三大核心开发库之一,其主要负责的是图形显示,所以叫Presentation(呈现)。作为新的图形引擎,WPF是基于DirectX的,当然增加了很多新的功能。其2D和3D引擎的强大看看Vista的界面就明白了,再加上其对Aero图形引擎的支持,更加让你刚到神奇。顺便提一下,Aero是专门为3D桌面开发的引擎,可以让桌面实现神奇的3D翻转,这绝对是操作系统有史以来的一次神奇尝试,虽然对硬件配置的要求也是惊人的,此前已有相关报道称,Vista对显卡十分挑剔就是出于运行Aero的考虑。
1.1.1 WPF的主要特性
图形服务
所有的图形(包括桌面的窗口等对象)都将通过Direct3D渲染,旨在提供统一的图形显示通道,以实现高级的图形表现效果。
凭借Direct3D渲染图形的好处是,操作系统可以将图形处理任务委托给计算机显示卡上的图形处理芯片GPU,以减轻CPU的负担。
WPF支持任意比例无损缩放的矢量化图形,支持在2D应用程序中进行3D模型的渲染和交互操作。
互操作性
WPF提供了同Win32的互操作性。通过嵌入模式,可以在Win32 代码中使用WPF,也可在WPF中使用Win32 代码。同Windows 窗体的互操作可通过ElementHost类和WindowsFormsHost类来实现。
媒体服务
WPF为二维图形提供了基本几何元素,以及一整套画刷、画笔、几何体和变形等工具。WPF的三维特性局限于Direct3D现有的功能。然而,WPF提供了与用户界面、文档和媒体介质等的紧密集成。这使得三维界面、三维文档、三维媒体成为可能。
WPF支持大多数通用图像格式,以及WMV, MPEG and AVI等视频格式。WPF支持时基动画而不是桢动画,从而使动画的播放速度不受系统性能的影响。WPF使用ClearType技术实现文本渲染。ClearType提供了次像素级定位、自然步幅、纵向反锯齿等特性。WPF同时支持OpenType字体特性。
数据绑定
WPF 内置了一系列数据服务,使得开发人员可以在应用程序之间自如地绑定和操纵数据。WPF提供三种数据绑定方式:
一次性:客户端忽略服务器端的数据更新的情况
单向性:客户端对服务器端的数据有只读权限的情况
双向性:客户端对服务器端的数据拥有读写权限的情况
用户界面
WPF内置一系列控件:按钮、菜单、列表框等。
WPF提出了一个功能强大的概念:将控件的逻辑层和表现层分离。通过重载控件的模板就可彻底改变其外观。控件可包容任何其它控件,从而通过组合实现无限的控制功能。
1.1.2 WPF架构
1.1.3 WPF程序
WPF除了构建传统的独立运行桌面应用程序,也支持基于XAML技术的浏览器应用(XBAP)。两种类型应用的编程模型很相似。
1) 桌面应用程序是可信度最高,采用ClickOnce或MSI等软件安装在本地计算机的应用程序,对计算机资源拥有完全的访问权限。
2) 浏览器应用程序应用虽然看起来像是在浏览器内运行,实质上是创建了另一个进程。Internet Explorer 用户可以将 XBAP 直接下载到浏览器,而不必部署安装版 WPF 应用程序。此应用程序在 Internet Explorer 内运行,可以提供基于 WPF 的用户界面。但是从 Internet 网站下载和运行代码是一项危险的操作。为保护用户免遭恶意开发者的攻击,所有从 Internet 下载的 XBAP 都在部分信任沙箱中运行。基于 .NET Framework 提供的代码访问安全性,该沙箱会限制 XBAP 的操作。例如,从 Internet 下载的 XBAP 不能创建独立窗口或启动新窗口,不能显示由 XBAP 本身启动的保存对话框或访问隔离存储区以外的文件系统。尽管沙箱规定了种种限制,XBAP 仍然可以使用大部分的 WPF 功能,包括二维和三维图形、动画、屏幕文档、图像、视频等。
问题
在WPF中,WinForm究竟是否能完全能取代WebForm?如果说原有的Winform属于胖客户,那最终可以取代WebForm的Winform到底属于胖客户还是瘦客户?
WPF之中,本身就有分为Windows及Browser两种应用程序,另外再加上真正在Web上运行的WPF/E,故它其实是同时具备三种型态能力的. 然而虽然微软对WPF期望很大,但毕竟不能不面对现实,ASP.NET的人口更大,传统HTML仍主宰着现在及未来的网络世界,您可以反问自己一个问题,Flash出来后,为什么HTML没有消失?故同理可证,WPF出来后,ASP.NET不会消失,且下一版本的ASP.NET已在设计中,会随着Visual Studio 2008一并推出,最终会形成WPF与ASP.NET各占一片天的两大势力。
1.2应用程序生命周期
App.xaml <Application x:Class="WpfApplication_LifeCyclew.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Startup="Application_Startup" Activated="Application_Activated" Deactivated="Application_Deactivated" Exit="Application_Exit" DispatcherUnhandledException="Application_DispatcherUnhandledException" SessionEnding="Application_SessionEnding" > <Application.Resources>
</Application.Resources> </Application>
App.xaml.cs public partial class App : Application { bool isApplicationActive;
/// <summary> /// StartupUri="Window1.xaml" /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Application_Startup(object sender, StartupEventArgs e) { Window2 win = new Window2(); win.Show(); }
private void Application_Activated(object sender, EventArgs e) { this.isApplicationActive = true; }
private void Application_Deactivated(object sender, EventArgs e) { this.isApplicationActive = false; }
private void Application_Exit(object sender, ExitEventArgs e) { Application.Current.Shutdown(-1); }
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { MessageBox.Show(e.Exception.Message); }
private void Application_SessionEnding(object sender, SessionEndingCancelEventArgs e) { string msg = string.Format("{0}. End session?", e.ReasonSessionEnding); e.Cancel = true; } private void Application_Exit(object sender, ExitEventArgs e) { Application.Current.Shutdown(-1); } } |
1.3两种WPF程序
1.3.1 WPF应用程序
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300"> <Grid> <Button Height="23" Margin="96,74,108,0" Name="button1" VerticalAlignment="Top" Click="button1_Click">ClickButton</Button> </Grid> </Window>
/// <summary> /// Window1.xaml 的交互逻辑 /// </summary> public partial class Window1 : Window { public Window1() { InitializeComponent(); }
private void button1_Click(object sender, RoutedEventArgs e) { MessageBox.Show("成功点击按钮!"); } } |
1.3.2 WPF浏览器应用程序
<Page x:Class="WpfBrowserApplication1.Page1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1"> <Grid> <Button Height="23" Margin="96,74,108,0" Name="button1" VerticalAlignment="Top" Click="button1_Click">ClickButton</Button> </Grid> </Page>
/// <summary> /// Page1.xaml 的交互逻辑 /// </summary> public partial class Page1 : Page { public Page1() { InitializeComponent(); }
private void button1_Click(object sender, RoutedEventArgs e) { MessageBox.Show("成功点击按钮!"); } } |
1.3.3 程序区别
1. Window / Page
2. 项目部署区别
3. 安全限制
在因特网区域,wpf的不安全特性:
1) 访问本地文件系统;
2) 访问注册表;
3) 与非托管代码进行交互;
4) 启动新的窗口。
下图演示了区域、权限集、权限和资源之间的关系。
在浏览器中打开新窗口的错误界面:
解决方案:
数字签名,部署到GAC
1.3.4 通用开发方式
创建同一个库,既可使用于WinApp程序,又可作为Web程序加载于浏览器中。注意,要在运行时检测状态,IsBrowserHosted属性判断。
1.4小心ClickOnce缓存
ClickOnce部署,基于应用程序版本号。
Mage –cc : 清除所有仅联机应用程序的已下载应用程序缓存。
1.5 按需下载文件
1.6 DeepZoom技术
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Loose XAML PhotoGallery"> <Page.Resources> <ScaleTransform x:Key="transform" ScaleX="3" ScaleY="{Binding Path=ScaleX, RelativeSource={RelativeSource Self}}"/> <LinearGradientBrush x:Key="shinyBrush" StartPoint="0,0" EndPoint="0,1"> <GradientStop Offset="0" Color="Gray"/> <GradientStop Offset="0.3" Color="#FF222222"/> <GradientStop Offset="0.3" Color="Black"/> <GradientStop Offset="0.9" Color="Black"/> <GradientStop Offset="0.9" Color="#FF222222"/> <GradientStop Offset="1" Color="Gray"/> </LinearGradientBrush> </Page.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition/> <RowDefinition Height="55"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="70"/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Rectangle Grid.ColumnSpan="3" Fill="{StaticResource shinyBrush}"/> <Rectangle Grid.Row="2" Grid.ColumnSpan="3" Fill="{StaticResource shinyBrush}"/> <Grid Grid.Row="1" Background="White"> <Slider Margin="20" Orientation="Vertical" Value="{Binding Path=ScaleX, Source={StaticResource transform}, Mode=TwoWay}" Minimum="1" Maximum="10" Height="100"/> </Grid> <ListBox x:Name="pictureBox" Background="AliceBlue" Grid.Row="1" Grid.Column="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <WrapPanel/> </ItemsPanelTemplate> </ListBox.ItemsPanel>
<Image Source="Autumn Leaves.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Creek.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Desert Landscape.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Dock.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Forest.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Forest Flowers.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Frangipani Flowers.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Garden.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Green Sea Turtle.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Humpback Whale.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Oryx Antelope.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Toco Toucan.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Tree.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Waterfall.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/> <Image Source="Winter Leaves.jpg" Margin="3,8" Height="35" LayoutTransform="{StaticResource transform}"/>
</ListBox> </Grid> </Page>
|
ScaleTransform按元素的水平和垂直尺寸进行缩放。其中,ScaleX控制文字的水平缩放比率,ScaleY控制文字的垂直方向的比率 。
1.7 多媒体流实例
1.8与浏览器交互
XBAP程序在浏览器中加载的方式:
1) 直接加载
2) Iframe嵌入
<iframe src="Wpf/InteractiveWithWpfBrowserApplication.xbap"></iframe>
方法1: URL
http://eking/InteractiveWithWpfBrowserApplication/InteractiveWithWpfBrowserApplication.xbap?a=1&b=2
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.Specialized; using System.Windows.Interop; using System.Web; using System.Deployment.Application; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes;
namespace EkingInteractiveWithWpfBrowserApplication { /// <summary> /// Page1.xaml 的交互逻辑 /// </summary> public partial class Page1 : Page { public Page1() { InitializeComponent();
StringBuilder sb = new StringBuilder();
sb.Append("URL参数:"); NameValueCollection paramsQuery = GetQueryStringParameters(ApplicationDeployment.CurrentDeployment.ActivationUri); foreach (string key in paramsQuery.Keys) { sb.Append( "key: " + key + ", value: " + paramsQuery[key] ); sb.Append("; "); } this.label1.Content = sb.ToString();
}
private NameValueCollection GetQueryStringParameters(Uri launchUri) { NameValueCollection nameValueTable = HttpUtility.ParseQueryString(launchUri.Query); return nameValueTable; }
} }
|
方法2: Cookie (未试通)
Application.GetCookie(ApplicationDeployment.CurrentDeployment.ActivationUri);
注:获得正在浏览的XBAP网页的URI
1) BrowserInteropHelper.Source
2) System.Deployment.Application.ApplicationDeployment.CurrentDeployment.ActivationUri
1.9目前开发存在的问题
1. 工具栏停靠不好实现,没有父窗口。
2. 属性窗口的处理。
3. WPF中嵌入的Win32图形控件,控件使用GDI+技术。控件在WPF中事件无法响应。
4. WPF浏览器应用程序如何调试?
5. WPF浏览器应用程序与外部网页交互能力太弱。