移动互联网(windows phone && windows 8 开发)

专著技术开发,成就美好未来
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

做了两年的WPF开发,主要参与开发水利、铁路、广播电视、电力行业的监控项目,总的来说WPF做这类项目,还是有一手的,我本人使用的也比较得心应手。因一直关注着移动互联网的发展,今年年初从原公司辞职,转向移动互联网方向,现从事windows移动方面的开发,上班几个月来,感觉还行,由于做了两年的WPF,转windows phonewindows 8,还比较顺利,独立开发的第一个应用已经上线,心情愉悦。现对WPF的几个技术要点做下总结(关于WPF的简介什么的在这就不做总结,这类的文章比较多),希望对大家有帮助。

 

一、      几个关键类 

 

l         System.Threading.DispatcherObject

WPF 中的大多数对象是从 DispatcherObject 派生的,这提供了用于处理并发和线程的基本构造。 WPF 基于调度程序实现的消息系统。其工作方式与常见的 Win32 消息泵非常类似;事实上,WPF 调度程序使用 User32 消息执行跨线程调用。Wpf为单线程模型,把整个用户界面将被宿主到单一的线程。

l         System.Windows.DependencyObject

WPF主要通过属性与界面交互,提供一套强大是属性系统,并使用声明式的编程语法。该属性系统是从 DependencyObject 类型派生的。

l         System.Windows.Media.Visual

Visual 类用于生成可视化对象的树,可以看成一个图形对象,WPF中呈现的每个元素都是一个可视化的对象。

l         System.Windows.UIElement

UIElement 定义核心子系统,包括 LayoutInput Event。引入了增强的事件传递系统,路由事件。

l         System.Windows.FrameworkElemen

关于应用程序布局,并引入了两个新的概念 数据绑定和样式,数据绑定最值得关注的功能是 数据模板

l         System.Windows.Controls.Control

添加了一些属性,字体、前景色,提供对控件模板的支持,开发人员可以使用自定义样式改变控件的标准呈现

Control FrameworkElementUIElementVisual(从左至右继承)

 

二、      视觉树和逻辑树

 

l         逻辑树为对象树,可提供开发人员变成遍历、扩充、以及编程修改用户界面。LogicalTreeHelper有了逻辑树的存在,内容模型可以方便地循环访问其潜在子对象,因而可以得到扩展。资源通过逻辑树查找

l         视觉树为的组成界面的各个元素,呈现用户界面,当修改控件外观、编写模板时使用。路由事件的事件路由特性大多数遍历可视化树。

 

三、      ResourceDictionary  

 

l         资源字典 是使用键值对来存储资源(Resource

l         资源的作用就近原则

l         资源合并

 

四、           属性变更通知

 

l         INotifyPropertyChangeSystem.ComponentModel

向客户端发出某一属性值更改的通知。PropertyChanged

l         ObservableCollection<T>类,它是实现 INotifyCollectionChanged 接口的数据集合的内置实现。

表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知

 

五、      Commands (命令)作用和好处

 

l         减少业务代码与UI的耦合度。

l         Command可以集中管理不同操作。

l         Command既和操作关联,又和界面关联。

 

六、      Routed Events(路由事件) 

 

l         定义

WPF提供了一套新的事件处理系统—路由事件

定义:事件按照指定的线路进行传递的机制。

l         CLR事件的区别

CLR事件,可以与一个或多个元素相关联,但是每个关联的元素需要显示进行订阅事件,否则CLR将忽略该对象。

WPF路由事件提供一中不同的机制,路由事件可在WPF元素树上进行向上或向下的传递,无论元素是否关联订阅,位于元素树上下级事件都有机会处理事件。

l         WPF使用路由事件的原因

WPF这中事件传递机制,与其内容模型有密切关联Eg:一个buttoncontent属性赋值一image副图片,当输入事件产生时,比如用户点击button按钮,,会产生一个click事件,这是image也要处理鼠标事件,如果按照CLR事件处理的话,那意味着开发人员需要同时订阅imagebutton的事件。目前button的内容是一个简单的元素树结构,还可以接受,如果是一个非常复杂的元素树结构,那需要订阅的事件就非常可观啦,非常复杂。

用途

1、  定义公用处理程序、组合自己的控件或者自定义控件类。

2、  应用程序间的不同元素交换信息。

3、  元素树上的元素通信。

l         事件路由策略

u      冒泡(bubble):事件源先调用事件处理程序,然后沿着元素树向上传递到父元素,一直到元素树的根。(事件源—>根元素)

u      直接(direct):事件只在被附加事件的元素上触发,并不会传递给其他元素。支持类处理机制,可以用在EventSetter and EventTrigger

u      隧道(tunnel):根元素先调用事件处理程序,然后沿着元素树向下传递,一直到事件源元素。

(根元素—>事件源)。隧道事件以Preview标示开始。

 

七、      依赖属性

 

什么是依赖属性                                                                                                         

WPF使用一组服务(属性赋值的规则,包括属性变更回调(PropertyChangedCallback强制值回调(CoerceValueCallback)、属性验证回调(ValidateValueCallback、计算、验证、限制)对CLR属性进行扩展,这个服务叫做属性系统,属性系统支持的属性为依赖属性。

实例:

View Code
 1 public class SimpleDO : DependencyObject
 2 {
 3     public static readonly DependencyProperty ValueProperty =
 4         DependencyProperty.Register("Value"typeof(double), typeof(SimpleDO),
 5             new FrameworkPropertyMetadata((double)0.0,
 6                 FrameworkPropertyMetadataOptions.None,
 7                 new PropertyChangedCallback(OnValueChanged),
 8                 new CoerceValueCallback(CoerceValue)), 
 9                 new ValidateValueCallback(IsValidateValue));
10  
11     public double Value
12     {
13         get { return (double)GetValue(ValueProperty); }
14         set { SetValue(ValueProperty, value); }
15     }
16  
17     private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
18     {
19         Console.WriteLine("ValueChanged new value is {0}", e.NewValue);
20     }
21  
22     private static object CoerceValue(DependencyObject d, object value)
23     {
24         Console.WriteLine("CoerceValue value is {0}", value);
25         return value;
26     }     
27     
28     private static bool IsValidateValue(object value)
29     {
30         Console.WriteLine("ValidateValue value is {0}", value);
31         return true;
32     }  
33 }     

 

.NET属性有什么不同                                                     

l         定义方式,依赖属性DependcyObjectpublic的方法,避免实例化,这就需要依赖属性采用一种注册的方式定义。

l         优化存储,较少开销(GetValueSetValue内部使用了一个高效的存储结构),并且依赖属性为静态字段,较少内存分配的空间。

l         处理变更通知、验证、限制,为了提高性能,当属性值改变后,WPF先调用验证,如果验证通过在顺寻执行,如果不通过就不调用后面的操作。

l         可以存储多个值(同一属性拥有多个值)

l         属性值继承(属性值沿着元素树(逻辑树,可视化树)向下传递),对多种提供器支持。

l         属性触发器(eg:鼠标放上、离开按钮的颜色改变)

WP使用其做什么                                                    

WPF提供了强大的属性系统,可以支持数据绑定、样式、动画、附加属性等功能

 

八、      样式

 

l         样式是一系列对象属性的集合。在类型的不同实例之间共享资源、属性、事件的处理程序,可以看做一组属性值应用到多个元素的捷径。对属性的批处理。

l         代码重用,比资源更好的可重用性和扩展性。

l         把一些控件的通用属性抽离成样式,是这些控件保持一样的风格。并且可以通过样式轻松的改变控件的样式。

l         UI对象的结构,样式和行为分离这是一种很好的设计

l         Style元素属性、资源、事件

    实例:Style中定义了资源SolidColorBrush,定义了属性HeightWidth,以及使用了EventSetter来定义了Loaded事件的处理。

<Window>

 <Window.Resources>

 <Style TargetType="{x:Type Button}" x:Key="ButtonStyle">

 <Style.Resources>

      <SolidColorBrush x:Key="brush" Color="Yellow"/>

        </Style.Resources>

            <Setter Property="Height" Value="22"/>

           <Setter Property="Width" Value="60"/>

            <EventSetter Event="Loaded" Handler="Button_Loaded"/>

        </Style>

     </Window.Resources>

     <x:Code>

        <![CDATA[

            void Button_Loaded(object sender, RoutedEventArgs e)

             {

                 MessageBox.Show((sender as Button).Name + " Loaded");

             }

         ]]>

     </x:Code>

     <Grid>

         <Button x:Name="button1" Style="{StaticResource ButtonStyle}" Background="{DynamicResource brush}"/>

        <Button x:Name="button2" Style="{StaticResource ButtonStyle}" Background="{DynamicResource brush}" Margin="156,144,286,145" />

     </Grid>

 </Window>

 

 

 

九、      模板

 

l         模板用来定义或重定义控件外观的。WPF的任何控件都有视觉树和逻辑树。但是Style有它自己的局限性:它只能修改控件已有树型结构的属性,不能修改控件的树型层次结构本身。就想一台电脑使用Style可以改变硬盘、内存等,但不能改变电脑本身。使用模板可以,把电脑变成小汽车。

l         包括三大模板 ControlTemplateItemsPanelTemplate(指定用于项的布局的面板)为控件模板,DataTemplate为数据模板,他们都是派生自FramworkTemplate抽象类。

 

十、      触发器

 

某个属性值更改时,或某个事件引发时,触发器会相应地设置属性或启动操作(如动画操作)。Style ControlTemplate DataTemplate 都具有 Triggers 属性,该属性可以包含一组触发器。 有各种类型的触发器。

种类                                                                 

l         单一条件触发器

1.         属性触发器(Property Trigger

属性触发器是在当某个依赖属性的值发生变化时触发执行一个Setter的集合,当属性失去这个值时,这些被触发执行的Setter集合会自动被撤销。

Eg <Style TargetType="Button">

            <Setter Property="Height" Value="22"/>

            <Setter Property="Width" Value="150"/>

            <Style.Triggers>

                <Trigger Property="IsMouseOver" Value="true">

                    <Setter Property="Cursor" Value="Hand" />

                </Trigger>

            </Style.Triggers>[l1] 

         </Style>

2.         事件触发器(EventTrigger

根据事件改变触发或启动一组操作。它和PropertyTrigger相似,但是,它的内部不是简单的Setter集合,而是TriggerAction是实例。

Eg:一个圆颜色渐变。

   <Ellipse Width="200" Height="200" Name="myEllipse">

                <Ellipse.Fill>

                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">

                        <LinearGradientBrush.GradientStops>

                            <GradientStop Color="Red" Offset="0" x:Name="SColor" />

                            <GradientStop Color="Green" Offset="1" x:Name="EColor" />

                        </LinearGradientBrush.GradientStops>

                    </LinearGradientBrush>

                </Ellipse.Fill>

                <Ellipse.Triggers>

                    <EventTrigger RoutedEvent="Ellipse.Loaded">[l2] 

                        <EventTrigger.Actions>[l3] 

                            <BeginStoryboard>

                                <Storyboard>

                                    <ColorAnimation From="Red" To="Green" Duration="0:0:4" 

                                                     AutoReverse="True" RepeatBehavior="Forever"

                                    Storyboard.TargetProperty="Color"

                                    Storyboard.TargetName="SColor"/>

                                    <ColorAnimation From="Green" To="Black" Duration="0:0:4"

                                              AutoReverse="True" RepeatBehavior="Forever"

                                    Storyboard.TargetProperty="Color"

                                    Storyboard.TargetName="EColor" />[l4] 

                                </Storyboard>

                            </BeginStoryboard>

                        </EventTrigger.Actions>

                    </EventTrigger>

                </Ellipse.Triggers>

            </Ellipse>

3.         数据触发器(DataTrigger)

数据触发器和属性触发器除了面对的对象类型不一样外完全相同。数据触发器是来检测非依赖属性------也就是用户自定义的.NET属性-----的值发生变化时来触发并调用符合条件的一系列Setter集合。

Egdatagrid控件的某一行的值为某一值时,行颜色改变。

<Style TargetType="DataGridCell">

            <Style.Triggers>

                <DataTrigger Binding="{Binding Path=S_STUFFNAME[l5] }" Value="李四">

                    <Setter Property="Background" Value="Red"></Setter>

                </DataTrigger>

            </Style.Triggers>

      </Style>

l         多条件触发器

上面讨论的都是针对单个条件的触发器,也就是说当某一个条件满足时就会触发。而现实中我们可能需要满足很多个条件时才触发一系列操作,这个时候就需要用到MultiDataTriggerMultiTriggerMutliDataTriggerMultiTrigger都具有一个Conditions集合用来存放一些触发条件,这里的Condition之间是and的关系,当所有条件都满足时,Setter集合才会被调用。根据名字就可以看清楚:MultiDataTrigger用来实现多个数据触发器(只用于普通.NET属性)满足条件时调用;MultiTrigger用来实现多个属性触发器(用于依赖属性)满足条件时调用。

Eg:多条件触发器

        <MultiTrigger>

            <MultiTrigger.Conditions>

                <Condition Property="Visibility " Value="Visible" />

                <Condition Property="IsEnabled" Value="true" />[l6] 

            </MultiTrigger.Conditions>

            <Setter Property="BorderBrush" Value="Red"/>

            <Setter Property="FontSize" Value="14" />

            <Setter Property="FontWeight" Value="Bold" />

            <Setter Property="Foreground" Value="Red" />[l7] 

        </MultiTrigger>

 


 [l1]触发器

 [l2]事件触发器

 [l3]事件触发器的TriggerAction集合

 [l4]两个目标值之间的 Color 属性值进行动画处理。

 [l5]自定义实体属性,当属性值为李四时,行Background颜色为红色

 [l6]触发条件

 [l7]触发结果