WPF簡單教程:控件ViewBox

WPF作爲一種新型界面技術,採用了XML方式描述界面。提供了很多預定義空間,其中由一些非常有用的控件。ViewBox就是其中一例,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 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。
這裏寫圖片描述
代碼運行截圖

這裏寫圖片描述
窗口縮放的效果

可以看到只有添加了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>

這裏寫圖片描述

以上是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>

這裏寫圖片描述
通過一些列空間組合提供了一個類似於瀏覽器縮放頁面的結構(類似Word編輯頁面的縮放操作),最基本的結構是一個巨大無比的Grid面板,將ViewBox固定在Grid面板上,縮放Grid面板,就能同步縮放ViewBox中包含的內容。

這裏寫圖片描述
初始運行狀態顯示
這裏寫圖片描述
窗口全屏顯示
這裏寫圖片描述
圖形放大100倍,可以看到滾動條縮短,圖形放大
這裏寫圖片描述
縮小100倍,原本的圖形變得非常小,幾乎看不見,這個時候,面板縮小被放置在了ScrollViewer的中央。

可以看到,類似於瀏覽器頁面的縮放操作使用的正是複雜的結構組合而成。
好了ViewBox的空間基本要點講解完成。歡迎大家評論反饋。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章