添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
WPF之路-常用布局控件二

WPF之路-常用布局控件二

Grid容器

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

调整行与列

通过Grid.RowDefinitions来定义行,Grid.ColumnDefinitions来定义列


<Window x:Class="WPF_Code.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.RowDefinitions定义行-->
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition><!--一行-->
            <RowDefinition></RowDefinition><!--一行-->
        </Grid.RowDefinitions>
        <!--Grid.ColumnDefinitions定义列-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition><!--一列-->
            <ColumnDefinition></ColumnDefinition><!--一列-->
        </Grid.ColumnDefinitions>
    </Grid>
</Window>

上例中定义了两行两列,因此Grid被分割成了四个部分

布局舍入

Grid的 宽度和高度设置的三种方法:

  1. 指定数值 如: Width = "50" ,不建议使用此方式
  2. 等比例设置: Width="*" Width = "2*" Width = "3*" 这样的话,三个单元则以1:2:3 比例设置大小


<!--Grid.ColumnDefinitions定义列-->
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*"></ColumnDefinition><!--一列-->
           <ColumnDefinition Width="2*"></ColumnDefinition><!--一列-->
           <ColumnDefinition Width="3*"></ColumnDefinition><!--一列-->
       </Grid.ColumnDefinitions>
   </Grid>
  1. 自适应: Width = “Auto” 单元格适应内部控件大小 也就是说,元素的大小多大,分割的部分就会自动变成多大


<Window x:Class="WPF_Code.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.RowDefinitions定义行-->
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition><!--一行-->
            <RowDefinition Height="Auto"></RowDefinition><!--一行-->
        </Grid.RowDefinitions>
        <!--Grid.ColumnDefinitions定义列-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition><!--一列-->
            <ColumnDefinition Width="2*"></ColumnDefinition><!--一列-->
            <ColumnDefinition Width="3*"></ColumnDefinition><!--一列-->
        </Grid.ColumnDefinitions>
        <!--在第二行第一列上加一个按钮-->
        <Button Grid.Column="0" Grid.Row="1">你好</Button>
    </Grid>
</Window>

当Grid的大小按比例模式进行分割时,可能某一部分的大小不是一个整数,此时如果在该部分加一个整数大小像素的图片,就会变得模糊,这是由于WPF的混合锯齿是的最小单元格的界面显示模糊,为了解决这种情况,则需要设置Grid 的UseLayoutRounding 属性,以增加抗锯齿效果

<Grid UseLayoutRounding="True">

将元素跨行或跨列安放

ColumnSpan 属性表示跨列 RowSpan 属性表示跨行

示例代码<Button Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="2">你好</Button>,如下图


<Window x:Class="WPF_Code.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 UseLayoutRounding="True">
        <!--Grid.RowDefinitions定义行-->
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition><!--一行-->
            <RowDefinition ></RowDefinition><!--一行-->
        </Grid.RowDefinitions>
        <!--Grid.ColumnDefinitions定义列-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition><!--一列-->
            <ColumnDefinition Width="2*"></ColumnDefinition><!--一列-->
            <ColumnDefinition Width="3*"></ColumnDefinition><!--一列-->
        </Grid.ColumnDefinitions>
        <!--在第二行第一列上加一个按钮-->
        <Button Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="2">你好</Button>
    </Grid>
</Window>

分割容器

GridSplitter 控件就是用来分割Grid控件的,必须放在Grid里面

示例代码<GridSplitter Grid.Column="1" VerticalAlignment="Stretch" Grid.RowSpan="3" HorizontalAlignment ="Left" Width="5"/>,如下图


<Window x:Class="WPF_Code.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 UseLayoutRounding="True">
        <!--Grid.RowDefinitions定义行-->
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition><!--一行-->
            <RowDefinition ></RowDefinition><!--一行-->
        </Grid.RowDefinitions>
        <!--Grid.ColumnDefinitions定义列-->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition><!--一列-->
            <ColumnDefinition Width="*"></ColumnDefinition><!--一列-->
            <ColumnDefinition Width="*"></ColumnDefinition><!--一列-->
        </Grid.ColumnDefinitions>
        <!--在第二行第一列上加一个按钮-->
        <Button Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Grid.ColumnSpan="1">你好</Button>
        <!--添加侵害容器-->
        <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" Grid.RowSpan="2" HorizontalAlignment ="Left" Width="5"/>
    </Grid>
</Window>

共享尺寸组

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

需要在父容器 设置属性 Grid.IsSharedSizeScope="True"


示例如下:

<Window x:Class="WPF_Code.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.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>
</Window>

Canvas面板

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

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


<Window x:Class="WPF_Code.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">
    <Canvas>
        <Button Canvas.Bottom="20" Canvas.Left="20">Hello</Button>
    </Canvas>
</Window>

上例描述的是元素在Canvas容器中的二维坐标,即X-Y坐标,还可以定义元素第三维坐标,即Z坐标f

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


<Window x:Class="WPF_Code.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">
    <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>
</Window>

调整矩形的顺序,如下:


<Window x:Class="WPF_Code.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">
    <Canvas>
        <Ellipse Fill="Gainsboro" Canvas.Left="25" Canvas.Top="25" Width="200" Height="200" />
        <Rectangle Canvas.ZIndex="1"  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="3" Fill="LightCyan" Canvas.Left="75" Canvas.Top="75" Width="50" Height="50" />
    </Canvas>
</Window>

InkCavas元素

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


Window x:Class="WPF_Code.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">
    <InkCanvas>
        <Button Content="Hello" InkCanvas.Bottom="50" InkCanvas.Left="30" />
    </InkCanvas>
</Window>

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


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

EditingMode="EraseByPoint"表示鼠标变成一个可擦除点的工具

EditingMode="EraseByStroke"表示鼠标变成一个可橡皮擦

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

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

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

EditingMode="None"表示没有任何反应

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

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


<Window x:Class="WPF_Code.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" Loaded="Window_Loaded" >
        <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>
</Window>


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPF_Code
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
        public MainWindow()
            InitializeComponent();
        /// <summary>
        /// 下拉框选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmb_model_SelectionChanged(object sender, SelectionChangedEventArgs e)
            //将InkCavas的EditingMode属性设置为选择后的属性
            //需要将SelectedItem强转成InkCanvasEditingMode类型
            this.incas.EditingMode = (InkCanvasEditingMode)this.cmb_model.SelectedItem;
        /// <summary>
        /// 窗体加载事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
            //Enum.GetValues用于检索指定枚举中常数值的数组
            //typeof用于获取类型的 System.Type 对象
            foreach (InkCanvasEditingMode item in Enum.GetValues(typeof(InkCanvasEditingMode)))
                //循环将InkCanvasEditingMode枚举值添加到下拉框中
                this.cmb_model.Items.Add(item);