WPF简单教程:控件ViewBox

WPF作为一种新型界面技术,采用了XML方式描述界面。提供了很多预定义空间,其中由一些非常有用的控件。ViewBox就是其中一例,ViewBox为界面提供了缩放能力。

使用方式

WPF简单教程:控件ViewBox_第1张图片

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="379*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="50*"/>
        Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="305*"/>
        Grid.RowDefinitions>
        <Menu Grid.ColumnSpan="3" Background="#FF804747" >Menu>
        <GridSplitter Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" Width="5" Background="#FF8B8B96"/>
        <Viewbox Grid.Row="1">
            <Canvas Height="100" Width="100">
                <Ellipse Fill="#FFF4F4F5" Height="100" Stroke="Black" Width="100"/>
            Canvas>
        Viewbox>

    Grid>
Window>

代码片段中在ViewBox中添加了Canvas,Canvas设置height=100,width=100,Canvas中又添加了一个圆形,圆形充满了整个Canvas。
WPF简单教程:控件ViewBox_第2张图片
代码运行截图

WPF简单教程:控件ViewBox_第3张图片
窗口缩放的效果

可以看到只有添加了ViewBox的部分中圆形得到了缩放,而上面的棕色条状区域并没有变化。

ViewBox的工作就是缩放其中的所有空间,但是在ViewBox之外的空间就不归他管了,ViewBox作为一种内容空间,与一般控件同样受到各种布局管理器的约束,我们可以利用这种约束来设计更加复杂的面板。

ViewBox默认等比缩放区域中的图形内容,但是我们可以通过ViewBox提供的属性来改变这种方式,其中ViewBox.Stretch,ViewBox.StretchDirection属性实现精确控制,详细用法请参考MSDN与WPF编程宝典。

工作原理

ViewBox的工作原理较为复杂,让我们通过一个案例来看一下。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="379*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="50*"/>
        Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="305*"/>
        Grid.RowDefinitions>
        <Menu Grid.ColumnSpan="3" Background="#FF804747" >Menu>
        <GridSplitter Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" Width="5" Background="#FF8B8B96"/>
        <Viewbox Grid.Row="1">
            <Canvas/>
        Viewbox>

    Grid>
Window>

WPF简单教程:控件ViewBox_第4张图片

以上是ViewBox中添加Canvas控件时候的现象,这里出现了一个问题,那就是当Canvas的width和height属性设置为auto(0)的时候,会发现视野中看不到任何控件。这是因为ViewBox的工作机制所致。

解惑

ViewBox的工作原理是缩放,使用ViewBox的时候需要明确两个概念,提供两个参数;

  1. 内部内容原始尺寸
  2. 外部ViewBox尺寸

ViewBox将根据这两个尺寸的关系对内部所有内容进行响应的缩放。但是上面的实例中使用了Auto,一般情况下Auto的含义是与父控件提供的区域对齐,但是对于ViewBox这种对于内部空间并没有约束能力的空间来说,Canvas无法得到合适的尺寸,因为ViewBox并不提供,那么Canvas的视图占据面积便是0,ViewBox无法得知合适的缩放比例。这种情况下利用能够明确得知边界大小的空间具有奇效。例如将Canvas换成Grid控件,Grid空间可以使用包裹内容(WrapContent)的方式,明确占据屏幕的尺寸。

当然如果使用Canvas空间也不麻烦,只需要如同第一个实例一样设置Canvas尺寸即可,当然一定要明确设定才行。

注意

ViewBox这种特性容易让人混淆,ViewBox并不是提供一个空间将其中的控件直接放大缩小,就好比很多人误解他为浏览器的页面放大缩小方式一样,无论你如何使用ViewBox,它内部的内容是不会变化的,会完全填充ViewBox的内部空间,而不会改变它占比。

它提供的方式是当你拉伸ViewBox的时候同步放大内部图形内容的能力。

  1. 内部内容原始尺寸:无法决定ViewBox占据的屏幕面积大小,无论设置多少都无法撑开ViewBox,他的作用能够决定ViewBox中的图形密度,尺寸越大,代表着同等屏幕占比的ViewBox能够放置更多空间。
  2. 外部ViewBox尺寸:真正决定ViewBox屏幕空间占比的参数,与内容原始尺寸配合,决定内容缩放倍数。

提供一个案例

<Window x:Class="DIAGEXP.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DIAGEXP"
        mc:Ignorable="d"
        Title="DIAGEXP" Height="500" Width="800">
    <Grid UseLayoutRounding="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200*"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="80*"/>
        Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"/>
            <RowDefinition Height="554*"/>
        Grid.RowDefinitions>
        <Menu Grid.ColumnSpan="3">
            <MenuItem Header="_File" Margin="0">
                <MenuItem Header="Exit" HorizontalAlignment="Left" Width="144"/>
            MenuItem>
            <MenuItem Header="_Help">
                <MenuItem Header="AboutSoftware" HorizontalAlignment="Left" Width="144"/>
            MenuItem>
        Menu>
        <GridSplitter Grid.Column="1" Grid.Row="1" Width="5" HorizontalAlignment="Stretch"/>
        <ScrollViewer Grid.Column="2" Grid.Row="1">
            <StackPanel Grid.Column="2" Grid.Row="1">
                <Expander Header="通用控件">
                    <Grid Background="#FF6276B9" Height="400"/>
                Expander>
                <Expander Header="可见控件">
                    <Grid Background="#FF912F2F" Height="400"/>
                Expander>
                <Expander Header="全部控件">
                    <Grid Background="#FF3BBD59" Height="400">
                        <Button Content="放大100" HorizontalAlignment="Left" Margin="34,64,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
                        <Button Content="缩小100" HorizontalAlignment="Left" Margin="84,145,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
                    Grid>
                Expander>
            StackPanel>
        ScrollViewer>
        <ScrollViewer Grid.Row="1" Name="ScrollOperation" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
            <Grid Name="BaseP" ShowGridLines="True" Width="10000" Height="10000">
                <Viewbox>
                    <Canvas Background="White" Height="10000" Width="10000">
                        <Rectangle Fill="#FFF4F4F5" Height="20" Canvas.Left="47" Stroke="Black" Canvas.Top="37" Width="80"/>
                    Canvas>
                Viewbox>
            Grid>
        ScrollViewer>
    Grid>
Window>

WPF简单教程:控件ViewBox_第5张图片
通过一些列空间组合提供了一个类似于浏览器缩放页面的结构(类似Word编辑页面的缩放操作),最基本的结构是一个巨大无比的Grid面板,将ViewBox固定在Grid面板上,缩放Grid面板,就能同步缩放ViewBox中包含的内容。

WPF简单教程:控件ViewBox_第6张图片
初始运行状态显示
WPF简单教程:控件ViewBox_第7张图片
窗口全屏显示
WPF简单教程:控件ViewBox_第8张图片
图形放大100倍,可以看到滚动条缩短,图形放大
WPF简单教程:控件ViewBox_第9张图片
缩小100倍,原本的图形变得非常小,几乎看不见,这个时候,面板缩小被放置在了ScrollViewer的中央。

可以看到,类似于浏览器页面的缩放操作使用的正是复杂的结构组合而成。
好了ViewBox的空间基本要点讲解完成。欢迎大家评论反馈。

你可能感兴趣的:(C#学习感悟,WPF,简单教程,DIAGEXP)