天天看点

WPF入门03之布局元素

WPF布局原则—不应显示设置大小

为了控件的大小可以自适应容器,控件不应该显示设置宽高。比如这里的

<Grid></Grid>

标签就没有设置宽高(为了方便观察,设置了灰色的背景),当我们拖大拖小窗口时,可以看到grid元素也是跟随窗口变化而变化

<Window x:Class="ControlExercise.Window2"
        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:ControlExercise"
        mc:Ignorable="d"
        Title="Window2" Height="450" Width="800">
    <Grid Background="Gray">
        
    </Grid>
</Window>
           
WPF入门03之布局元素

反之,如果我们设置了宽高,不管怎么拖动窗口,Grid都是固定大小的。

<Grid Width="100" Height="100" Background="Gray">
        
    </Grid>
           
WPF入门03之布局元素

布局容器之Grid

Grid控件为WPF中最重要的布局容器

  • 通过

    Grid.RowDefinitions

    来定义行,

    Grid.ColumnDefinitions

    来定义列

以下代码定义了两行,两列,所以Grid被分割成了四个部分

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
    </Grid>
           
WPF入门03之布局元素
  • Grid定义宽度高度的三种方式
  1. 指定数值:(不建议)

    Width=50

2)等比例设置:

<ColumnDefinition Width="1*"></ColumnDefinition> <ColumnDefinition Width="2*"></ColumnDefinition> <ColumnDefinition Width="3*"></ColumnDefinition>

WPF入门03之布局元素

3)自适应 :

Width="Auto"

该单元格适应内部控件大小

  • 元素的跨行或跨列安放
WPF入门03之布局元素
  • GridSplitter 控件就是用来分割Grid控件的,必须放在Grid里面

    GridSplitter的作用是可以让用户拖动来改变grid行或列的宽度或高度,使用起来非常简单,把它加到Grid里的某一行或者某一列,再分配合适的空间如5个像素这样就可以了

<Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="5" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Left side</TextBlock>
        <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" />
        <TextBlock Grid.Column="2" FontSize="55" HorizontalAlignment="Center" VerticalAlignment="Center" TextWrapping="Wrap">Right side</TextBlock>
           
WPF入门03之布局元素
  • 共享尺寸组

SharedSizeGroup属性允许相同名的元素具有等大的效果

<!--定义一个父容器,Grid.IsSharedSizeScope="True"是必须的-->
    <Grid ShowGridLines="True" Grid.IsSharedSizeScope="True">
        
        <!--在父容器中定义了两行-->
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <!--在父容器的第一行定义一个子容器-->
        <Grid ShowGridLines="True" Name="grid_1" Background="blue" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <!--第一个子容器的第一列指定了SharedSizeGroup属性-->
                <ColumnDefinition  Width="50" SharedSizeGroup="A" ></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
        </Grid>

        <!--在父容器的第二行定义一个子容器-->
        <Grid ShowGridLines="True" Name="grid_2" Background="Green" Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <!--第二个子容器的第二列指定了SharedSizeGroup属性-->
                <ColumnDefinition  SharedSizeGroup="A" ></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
        </Grid>

    </Grid>
           
WPF入门03之布局元素

布局容器之StackPanel控件

堆栈面板:在单行或单列中放置子元素

在窗口中放

<StackPanel></StackPanel>

标签,stackPanel中放置3个button,1个Label,效果如下;可以看出,StackPanel默认会将子元素垂直排列

WPF入门03之布局元素

可以通过Orientation属性来控制子元素排列方向

Orientation="Horizontal"

表示水平排列

Orientation="Vertical"

表示垂直排列,它是默认的

WPF入门03之布局元素

Margin

属性为元素添加外边距

Margin="10,15,20,25"的四个值分别表示左、上、右、下的位置,如下图

WPF入门03之布局元素

MinWidth

属性可以控制元素的最小尺寸,也就是说该元素不可以小于设定的最小宽度值

MaxWidth

属性可以控制元素的最大尺寸,也就是说该元素不可以大于设定的最大宽度值

布局容器之WrapPanel控件

WrapPanel容器将子元素按行或列一个接一个进行排列,如果一行或一列放不下,元素会被挤到下一行或一列;同一行元素的高度一样(水平排列),同一列元素的宽度是一样的(竖直排列)

<WrapPanel>
            <Button Content="Button" />
            <Button Content="Button" />
            <!--这里只设置了一个button的高度,与它同一行的元素都变成了一样的高度-->
            <Button Content="Button" Height="50" />
            <Button Content="Button" />
            <Button Content="Button" />
            <Button Content="Button" />
            <Button Content="Button" />
            <Button Content="Button" />
    </WrapPanel>
           
WPF入门03之布局元素

布局容器之DockPanel控件

DockPanel支持让元素简单地停靠在整个面板的某一条边上,然后拉伸元素以填满全部宽度或高度。它也支持让一个元素填充其他已停靠元素没有占用的剩余空间

DockPanel有一个Dock附加属性,因此子元素用4个值来控制她们的停靠:Left、Top、Right、Bottom。Dock 没有Fill值。作为替代,最后的子元素将加入一个DockPanel并填满所有剩余的空间,除非DockPanel的LastChildFill属性为false,它将朝某个方向停靠

<DockPanel>
        <Button Content="Button"/>
        <Button Content="Button"/>
        <Button Content="Button"/>
        <Button Content="Button"/>
        <Button Content="Button"/>
    </DockPanel>
           
WPF入门03之布局元素

默认情况下,元素会依次横向排列,并填充整个空间

<DockPanel>
        <!--DockPanel.Dock属性可控制元素在DockPanle中依靠的位置-->
        <Button Content="Button" DockPanel.Dock="Top" />
        <Button Content="Button" DockPanel.Dock="Bottom"/>
        <Button Content="Button" DockPanel.Dock="Left"/>
        <Button Content="Button" DockPanel.Dock="Right"/>
        <Button Content="Button"/>
    </DockPanel>
           
WPF入门03之布局元素

布局容器之Canvas面板

Canvas面板是基于坐标的布局容器;Canvas中的子元素的位置是需要显性设定的固定位置,通过Canvas的属性Left/Rigth/Top/Bottom来设置子元素相对位置

下例是一个距离下边界20、左边界20位置的一个按钮

<Canvas>
        <Button Canvas.Bottom="20" Canvas.Left="20">Hello</Button>
    </Canvas>
           
WPF入门03之布局元素

下例中定义了三个图形,一个圆,三个矩形,它们之间的重叠是按默认的顺序叠加的(未定义过Z坐标的,其Z坐标是0),可以通过设定Canvas.ZIndex属性值或Panel.ZIndex来调整元素的重叠顺序,值越大的越靠前

<Canvas>
        <Ellipse Fill="Gainsboro" Canvas.Left="25" Canvas.Top="25" Width="200" Height="200" />
        <Rectangle Canvas.ZIndex="3"  Fill="LightBlue" Canvas.Left="25" Canvas.Top="25" Width="50" Height="50" />
        <Rectangle Panel.ZIndex="2" Fill="LightCoral" Canvas.Left="50" Canvas.Top="50" Width="50" Height="50" />
        <Rectangle Panel.ZIndex="1" Fill="LightCyan" Canvas.Left="75" Canvas.Top="75" Width="50" Height="50" />
    </Canvas>
           
WPF入门03之布局元素

当然也可以调整Z轴顺序,效果如下

WPF入门03之布局元素

布局容器之InkCavas

InkCavas是一个画图控件,它允许在它之上加载其它控件,比如加载一个按钮;可以通过InkCanvas的Right/Left/Bottom/Top属性来指定元素的位置

<InkCanvas>
        <Button Content="Hello" InkCanvas.Bottom="50" InkCanvas.Left="30" />
    </InkCanvas>
           

运行程序后,可发现,当鼠标移动到InkCanvas区域时,鼠标会变成一个黑点,按下鼠标左键移动会画出线条

InkCanvas

EditingMode

的属性可根据不同的值,设定图画的不同功能

EditingMode="EraseByPoint"

表示鼠标变成一个可擦除点的工具

EditingMode="EraseByStroke"

表示鼠标变成一个可橡皮擦

EditingMode="GestureOnly"

表示按下鼠标可画线,鼠标松开后所画的线条将消失

EditingMode="Ink"

表示按下鼠标可画出墨线,本属性值是默认的

EditingMode="InkAndGesture"

与Ink功能类似,但同时可以识别用户的手势

EditingMode="None"

表示没有任何反应

EditingMode="Select"

表示可以选择一个元素,可以移动它、删除它,改变形状等

下面通过将这些属性动态的加载到下拉框中,通过选择不同的属性值来体验不同的画图效果

其中我感觉Select很有用,基于此可以实现让客户拖动缩放控件的效果。关键是不需要任何代码,运行状态控件的选中,拖动,缩放都已经实现了,非常方便

WPF入门03之布局元素
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <InkCanvas  Grid.Row="1" Name="incas">
            <Button Content="Hello" InkCanvas.Bottom="50" InkCanvas.Left="30" />
        </InkCanvas>

        <ComboBox Grid.Row="0" Name="cmb_model" SelectionChanged="cmb_model_SelectionChanged" />
    </Grid>