WPF的基础知识

一个WPF应用程序从两个线程开始,分别负责用户界面(UI)的管理和渲染。托管代码为用户提供构建WPF所需要的各种功能,如布局和绑定等,通常用户界面管理线程使用该部分代码;非托管代码主要负责图形的叠加显示和渲染,那么使用该部分代码的是不能被用户接触的渲染线程,两个线程之间通过消息来传递数据。。

WPF的全称是Windows Presentation Foundation,意思是Windows描述语言。它的一个主要特性是设计人员和开发人员的工作很容易分开,设计人员的工作成果可以直接供开发人员使用。为此,必须理解XAML。WPF在建立应用程序时使用XAML。XAML表示可扩展的应用程序标记语言,Extensible Application Markup Lanuage。XAML是用于创建窗体的XML声明,它代表WPF应用程序的所有可视化部分和操作。虽然只可以编程利用WPF应用程序,但WPF是面向声明性编程的第一步,而声明性编程是编程业的趋势。声明性编程是指,不是利用编程语言,如C#、VB或Java,通过编程来创建对象,而是通过XML类型的编程来声明所有元素。

形状是WPF的核心元素。利用形状,可以绘制矩形、线条、椭圆、路径、多边形和折线等二维图形,这些图形用派生自抽象类Shape的类表示。下图描述了System.Windows.Shapes 名称空间中可用的图形:

Shape类说明
Line可以在坐标(X1,Y1)到(X2,Y2)之间绘制一条线
Rectangle使用Rectangle类,通过指定Width和Hieght可以绘制一个矩形
Ellipse使用Ellipse类,可以绘制一个椭圆
Path使用Path类可以绘制一系列直线和曲线。Data属性是Geometry类型。还可以使用派生自基类Geometry的类绘制图形,或使用路径标记语法来定义图形。
Polygon使用Polygon类可以绘制由线段连接而成的封闭图形。多边形由一系列赋予Points属性的Point对象定义
Polyline类似于Polygon类,使用Polyline也可以绘制连接起来的线段。与多边形的区别是折线不一定是封闭图形。
下面的XAML代码示例绘制了一个黄色笑脸,它用一个椭圆表示笑脸,两个椭圆表示眼睛,两个椭圆表示眼睛中的瞳孔,一条路径表示嘴型:

<Window x:Class="ShapesDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Canvas>
            
            <Ellipse Canvas.Left="10" Canvas.Top="10" Width="100" Height="100" Stroke="Blue" StrokeThickness="4" Fill="Yellow" />
            <Ellipse Canvas.Left="30" Canvas.Top="12" Width="60" Height="30" >
                <Ellipse.Fill>
                    <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                        <GradientStop Offset="0.1" Color="DarkGreen"/>
                        <GradientStop Offset="0.7" Color="Transparent"/>
                    </LinearGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
            <Ellipse Canvas.Left="30" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White"/>
            <Ellipse Canvas.Left="40" Canvas.Top="43" Width="6" Height="5" Fill="Black"/>
            <Ellipse Canvas.Left="65" Canvas.Top="35" Width="25" Height="20" Stroke="Blue" StrokeThickness="3" Fill="White"/>
            <Ellipse Canvas.Left="75" Canvas.Top="43" Width="6" Height="5" Fill="Black"/>
            <Path Name="mouth" Stroke="Blue" StrokeThickness="4" Data="M 40,74 Q 57,95 80,74"/>
                   
        </Canvas>
        
    </Grid>
</Window>
上述代码描述出的图形如下:


因为WPF基于矢量,所以可以重置每个元素的大小。基于矢量的图形现在可以缩放、旋转和倾斜。我们可以给Canvas元素的LayoutTransform属性添加ScaleTransform元素来让整个画布的内容在X和Y上放大2倍。

            <Canvas.LayoutTransform>
                <ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
            </Canvas.LayoutTransform>
旋转与绽放的执行方式相同,使用RotateTransform元素,可以定义旋转的角度(Angel属性是角度):
            <Canvas.LayoutTransform>
                <RotateTransform Angle="40"/>
            </Canvas.LayoutTransform>
对于倾斜,我们可以使用SkewTransform元素,此时可以指定X和Y方向的倾斜角度:
            <Canvas.LayoutTransform>
                <SkewTransform AngleX="20" AngleY="25"/>
            </Canvas.LayoutTransform>
为了同时执行旋转和倾斜操作,可以定义一个TransformGroup,它同时包含RotateTransform和SkewTransform,如下:
            <Canvas.LayoutTransform>
                <TransformGroup>
                    <RotateTransform Angle="40"/>
                    <SkewTransform AngleX="20" AngleY="25"/>
                </TransformGroup>               
            </Canvas.LayoutTransform>
我们也可以定义一个MatrixTransform,其中Matrix元素指定了用于拉伸的M11和M22属性,以及用于倾斜的M12和M21属性,如下:
            <Canvas.LayoutTransform>
                <MatrixTransform>
                    <MatrixTransform.Matrix>
                        <Matrix M11="0.8" M22="1.6" M12="1.3" M21="0.4"/>
                    </MatrixTransform.Matrix>
                </MatrixTransform>         
            </Canvas.LayoutTransform>
下面为上述几种变换的结果图:


对于平滑的颜色变化,可以使用LinearGradientBrush。这个画笔定义了StartPoint和EndPoint属性。使用这些属性可以为线性渐变指定二维坐标。默认的渐变方向是从(0,0)到(1,1)的对角线。定义其他值可以给渐变指定不同的方向。例如,StartPoint指定为(0,0),EndPoint指定为(0,1),就得到了一个垂直渐变;StartPoint不变,EndPoint值指定为(1,0),就得到了一个水平渐变。通过该画笔的内容,可以用GradientStop元素定义指定偏移位置的颜色值。在各个偏移位置之间,颜色是平滑过渡的。

<Button Content="Solid Color" Margin="12,12,411,269" Width="80" Height="30">
            <Button.Background>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                    <GradientStop Offset="0" Color="LightGreen"/>
                    <GradientStop Offset="0.9" Color="Green"/>
                    <GradientStop Offset="1" Color="DarkGreen"/>
                </LinearGradientBrush>
            </Button.Background>
        </Button>

使用RadialGradientBrush可以以放射方式产生平滑的颜色渐变,示例代码:

<Canvas Width="200" Margin="-1,135,304,21">
            <Path Canvas.Left="20" Canvas.Top="30" Stroke="Black">
                <Path.Fill>
                    <RadialGradientBrush GradientOrigin="0.2,0.2">
                        <GradientStop Offset="0" Color="LightBlue"/>
                        <GradientStop Offset="0.6" Color="Blue"/>
                        <GradientStop Offset="1.0" Color="DarkBlue"/>
                    </RadialGradientBrush>
                </Path.Fill>
                <Path.Data>
                    <CombinedGeometry GeometryCombineMode="Union">
                        <CombinedGeometry.Geometry1>
                            <EllipseGeometry Center="80,60" RadiusX="80" RadiusY="40"/>
                        </CombinedGeometry.Geometry1>
                        <CombinedGeometry.Geometry2>
                            <RectangleGeometry Rect="30,60 105 50"/>
                        </CombinedGeometry.Geometry2>
                    </CombinedGeometry>
                </Path.Data>
            </Path>
        </Canvas>

DrawingBrush可以定义用画笔绘制的图形,用画笔绘制的图形在GeometryDrawing元素中定义:

<Button Content="Drawing Brush" Margin="-1,56,374,195" Padding="10" Width="130" Height="60">
            <Button.Background>
                <DrawingBrush>
                    <DrawingBrush.Drawing>
                        <GeometryDrawing Brush="Red">
                            <GeometryDrawing.Pen>
                                <Pen>
                                    <Pen.Brush>
                                        <SolidColorBrush>Blue</SolidColorBrush>
                                    </Pen.Brush>
                                </Pen>
                            </GeometryDrawing.Pen>
                            <GeometryDrawing.Geometry>
                                <PathGeometry>
                                    <PathGeometry.Figures>
                                        <PathFigure StartPoint="70,40">
                                            <PathFigure.Segments>
                                                <BezierSegment Point1="90,37" Point2="130,46" Point3="150,63" />
                                                <LineSegment Point="120,110"/>
                                                <BezierSegment Point1="100,95" Point2="70,90" Point3="45,91"/>
                                                <LineSegment Point="70,40"/>
                                            </PathFigure.Segments>
                                        </PathFigure>
                                    </PathGeometry.Figures>
                                </PathGeometry>
                            </GeometryDrawing.Geometry>
                        </GeometryDrawing>
                    </DrawingBrush.Drawing>
                </DrawingBrush>
            </Button.Background>
        </Button>

要把图像加载到画笔中,可以使用ImageBrush元素。通过这个元素,显示ImageSource属性定义的图像。图像可以从文件系统中访问,或者在程序集的资源中访问。下面的示例是从文件系统中访问:

<Button Content="Image Brush" Width="100" Height="80" Margin="241,12,162,219" Foreground="White">
            <Button.Background>
                <ImageBrush ImageSource="D:\vs.2010\WindowsPresentationFoundation\Brush\Image\1.png" />
            </Button.Background>
        </Button>
从文件系统中访问图像有危险,假如这条路径不存在该图像文件,那么就会造成程序报错。

VisualBrush可以在画笔中使用其他WPF元素。如下代码为一个Button元素中包含一个矩形和另一个按钮:

<Button Content="Visual Brush" Width="100" Height="80" Margin="135,12,268,219">
            <Button.Background>
                <VisualBrush>
                    <VisualBrush.Visual>
                        <StackPanel Background="White">
                            <Rectangle Width="25" Height="25" Fill="Blue"/>
                            <Button Content="Drawing Button" Background="Red" />
                        </StackPanel>
                    </VisualBrush.Visual>
                </VisualBrush>
            </Button.Background>
        </Button>
我们可以给VisualBrush添加任意UIElement,还可以创建反射等有趣的结果。如下示例,在Button按钮里面利用VisualBrush添加一个MediaElement播放视频。并得到它的反射效果。
<Button Foreground="White" Margin="12,12,22,12">
            <StackPanel>
                <MediaElement x:Name="reflected" Source="D:\vs.2010\WindowsPresentationFoundation\Brush\Image\爱情惹的祸.mp4" Width="324" Height="122" />
                <Border Height="100" >
                    <Rectangle Height="125" Width="332">
                        <Rectangle.Fill>
                            <VisualBrush Opacity="0.35" Stretch="None" Visual="{Binding ElementName=reflected}">
                                <VisualBrush.RelativeTransform>
                                    <TransformGroup>
                                        <ScaleTransform ScaleX="1" ScaleY="-1"/>
                                        <TranslateTransform Y="1"/>
                                    </TransformGroup>
                                </VisualBrush.RelativeTransform>
                            </VisualBrush>
                        </Rectangle.Fill>
                    </Rectangle>
                </Border>
            </StackPanel>
        </Button>

这里面显示的按钮包含一个StackPanel,它包含一个播放视频的MediaElement和一个Border。Border边框包含一个VisualBrush填充的矩形。这支画笔定义了一个不透明值和一个变换。把Visual属性绑定到Border元素上。变换通过设置VisualBrush的RelativeTransform属性来完成。这个变换使用了相对坐标。把ScaleY设置为-1,完成Y方向上的反射。TranslateTransform在Y方向上移动变换。从而使反射效果位于原始对象的下面。

下图为显示结果:






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值