WPF基础五:UI①布局元素Canvas

布局


布局窗口的几条重要原则:

  • 不应显示设定元素(控件)的尺寸。
  • 不应使用屏幕坐标指定元素的位置。
  • 布局容器的子元素“共享”可用空间。
  • 合理嵌套布局容器。

布局的过程:

  • 测量阶段Measure:容器遍历所有子元素,询问子元素他们所希望的尺寸。
  • 排列阶段Arrange:容器在合适的位置放置子元素。

布局容器都派生自Panel类。

 

属性备注权限
Background背景public
Children子元素public
HasLogicalOrientation如果 Panel 的方向是在一个维度上,则为 true;否则为 falseprotected
HasLogicalOrientationPublic如果 Panel 的方向是在一个维度上,则为 true;否则为 falsepublic
InternalChildren获取子元素的 UIElementCollectionprotected
IsItemsHost如果此 Panel 实例是项宿主,则为 true;否则为 false。 默认值是 falsepublic
LogicalChildren获取一个枚举器,它可以循环访问此 Panel 元素的各个逻辑子元素。protected
LogicalOrientation如果面板支持只有一个维度的布局,则为面板的 Orientationprotected
LogicalOrientationPublic如果面板支持只有一个维度的布局,则为面板的 Orientationpublic
VisualChildrenCount获取此 Visual 实例中的子 Panel 对象数。protected
方法备注权限
CreateUIElementCollection创建一个新的 UIElementCollectionprotected
GetVisualChild获取指定索引位置处的此 Visual 的 Panel 子级protected
GetZIndex获取给定元素的 ZIndex 属性的值。public
OnIsItemsHostChanged指示 IsItemsHost 属性值已更改。protected
OnRender在 Panel 元素的呈现处理过程中,绘制 DrawingContext 对象的内容。protected
OnVisualChildrenChanged当修改可见对象的 VisualCollection 时调用。protected
SetZIndex设置给定元素的 ZIndex 附加属性的值。public
ShouldSerializeChildren确定是否应对面板的 Children 集合进行序列化。public
附加属性备注
ZIndex获取或设置一个值,该值表示元素在 Z 平面中的显示顺序

 

如果希望自定义,需要用到Panel的几个内部属性,还可能需要重新FrameworkElament类的MeasureOverride()方法和ArrangeOverride()方法。

布局属性

名称布局
HorizontalAlignment水平对齐特征
VerticalAlignment垂直对齐特征
Margin外边距
MaxHeight最大高度约束
MinHeight最小高度约束
Height高度
MaxWidth最大宽度约束
MinWidth最小宽度约束
Width宽度
以上均继承自FrameworkElament

 


Canvas


Object->DispatcherObject->DependencyObject->Visual->UIElement->FrameworkElement->Panel->Canvas

 

方法备注权限
ArrangeOverride排列 Canvas 元素的内容。protected
GetBottom返回给定依赖对象的 Bottom 附加属性的值。public
GetLayoutClip返回一个剪裁几何图形,它指示当 ClipToBounds 属性设置为 true 时要剪裁的区域。protected
GetLeft为给定的依赖对象获取 Left 附加属性的值。public
GetRight为给定的依赖对象获取 Right 附加属性的值。public
GetTop为给定的依赖对象获取 Top 附加属性的值。public
MeasureOverride测量 Canvas 的子元素,以便准备在 ArrangeOverride(Size) 处理过程中排列它们。protected
SetBottom设置给定的依赖对象设置上的 Bottom 附加属性值。public
SetLeft设置给定的依赖对象设置上的 Left 附加属性值。public
SetRight设置给定的依赖对象设置上的 Right 附加属性值。public
SetTop设置给定的依赖对象设置上的 Top 附加属性值。public

 

附加属性备注
Bottom获取或设置一个值,该值表示元素底部与其父 Canvas 底部之间的距离。
Left获取或设置一个值,该值表示元素左侧与其父 Canvas 左侧之间的距离。
Right获取或设置一个值,该值表示元素右侧与其父 Canvas 右侧之间的距离。
Top获取或设置一个值,该值表示元素顶部与其父 Canvas 顶部之间的距离。

 


Canvas示例


Canvas面板是基于坐标的布局。

 

Canvas内部是相对坐标,坐标值接受负数。这是一个坐标布局元素。

接着改变窗口尺寸:

测试2相对于左上角(Left、Top)的位置没变。

测试1相对于右下角(Bottom、Right)的位置没变。

可见当Canvas变化后,元素相对于Canvas的位置没有变化,即相对位置固定不变。


附加属性 Canvas.Top优先于Canvas.BottomCanvas.Left优先于Canvas.Right 。

看下列代码:

<Window x:Class="_5_UI详解.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:_5_UI详解"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Canvas Background="AliceBlue"  >
            <Canvas.Children >
                <TextBlock                
                Width="100"
                Height="100"
                Padding="0 30"
                TextAlignment="Center"                
                Background="Blue"
                Foreground="Pink"
                FontSize="24"
                Text="测试1" 
                Canvas.Bottom="100"
                Canvas.Right="100"    />
                <TextBlock
                Width="100"
                Height="100"
                Padding="0 30"
                TextAlignment="Center"                
                Background="Red"
                FontSize="24"
                Text="测试2" 
                Canvas.Left="100"
                Canvas.Top="100"
                Canvas.Bottom="100"
                Canvas.Right="100"  />
            </Canvas.Children>            
        </Canvas>
    </Grid>
</Window>

测试1:   Canvas.Bottom="100"
                Canvas.Right="100" 

 

测试2:   Canvas.Left="100"
                Canvas.Top="100"
                Canvas.Bottom="100"
                Canvas.Right="100"

运行结果:

测试1和测试2赋予了相同的Bottom和Right值,但是最终显示位置却不一样。因为附加属性 Canvas.Top优先于Canvas.BottomCanvas.Left优先于Canvas.Right 。


 

UIElement.ClipToBounds对Canvas的影响:值为True时,内部元素溢出部分会被裁剪。

修改:

 测试1: Canvas.Right="-30" 

Canvas : Width="790" Height="400"  ClipToBounds="True" 

使Canas固定大小,不随Window的变化而变化。

代码如下:

<Window x:Class="_5_UI详解.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:_5_UI详解"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Canvas Background="AliceBlue"  ClipToBounds="True"  Width="790" Height="400">
            <Canvas.Children >
                <TextBlock                
                Width="100"
                Height="100"
                Padding="0 30"
                TextAlignment="Center"                
                Background="Blue"
                Foreground="Pink"
                FontSize="24"
                Text="测试1" 
                Canvas.Bottom="100"
                Canvas.Right="-30"    />
                <TextBlock
                Width="100"
                Height="100"
                Padding="0 30"
                TextAlignment="Center"                
                Background="Red"
                FontSize="24"
                Text="测试2" 
                Canvas.Left="100"
                Canvas.Top="100"
                Canvas.Bottom="100"
                Canvas.Right="100"  />
            </Canvas.Children>            
        </Canvas>
    </Grid>
</Window>

 ClipToBounds="True" 时,运行:

拖动放大窗口:

发现测试1被裁剪了。

 

 ClipToBounds="False" 时,拖动放大窗口:

发现测试1未被裁剪了。


Panel.ZIndex对内部元素的影响:元素的默认ZIndex值为0,ZIndex值越大的元素,层叠越高。ZIndex值可以为正整数、负整数或0。ZIndex附加属性等同于Canvas.SetIndex方法。

使用第一部分代码,拖动缩小窗口:

测试2在测试1的上面

在测试1中加入Panel.ZIndex="1"

发现测试1在测试2的上面。

<Window x:Class="_5_UI详解.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:_5_UI详解"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Canvas Background="AliceBlue" >
            <Canvas.Children >
                <TextBlock                
                Width="100"
                Height="100"
                Padding="0 30"
                TextAlignment="Center"                
                Background="Blue"
                Foreground="Pink"
                FontSize="24"
                Text="测试1" 
                Canvas.Bottom="100"
                Canvas.Right="100"  
                     Panel.ZIndex="1"/>
                <TextBlock
                Width="100"
                Height="100"
                Padding="0 30"
                TextAlignment="Center"                
                Background="Red"
                FontSize="24"
                Text="测试2" 
                Canvas.Left="100"
                Canvas.Top="100"
                Canvas.Bottom="100"
                Canvas.Right="100"
                    />
            </Canvas.Children>            
        </Canvas>
    </Grid>
</Window>

下面用C#语言创建UI

MainWindow.xaml.cs

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 _5_UI详解
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            TextBlock myTextBlock1 = new TextBlock();
            myTextBlock1.Background = Brushes.Blue;
            myTextBlock1.Width = 100;
            myTextBlock1.Height = 100;
            myTextBlock1.Padding = new Thickness(0, 30, 0, 0);
            myTextBlock1.Text = "测试11";
            myTextBlock1.FontSize = 24;
            myTextBlock1.Foreground = Brushes.Pink;
            myTextBlock1.TextAlignment = TextAlignment.Center;
            Canvas.SetBottom(myTextBlock1,100);
            Canvas.SetRight(myTextBlock1, 100);
            Canvas.SetZIndex(myTextBlock1, 1);

            TextBlock myTextBlock2 = new TextBlock();
            myTextBlock2.Background = Brushes.Red;
            myTextBlock2.Width = 100;
            myTextBlock2.Height = 100;
            myTextBlock2.Padding = new Thickness(0, 30, 0, 0);
            myTextBlock2.Text = "测试22";
            myTextBlock2.FontSize = 24;
            myTextBlock2.TextAlignment = TextAlignment.Center;
            Canvas.SetLeft(myTextBlock2, 100);
            Canvas.SetTop(myTextBlock2, 100);

            Canvas myCanvas = new Canvas();
            myCanvas.Children.Add(myTextBlock1);
            myCanvas.Children.Add(myTextBlock2);

             //Grid grid = new Grid();
            //grid = this.Content as Grid;
            //grid.Children.Add(myCanvas);

           (this.Content as Grid).Children.Add(myCanvas);

        }
    }
}

MainWindow.xaml

<Window x:Class="_5_UI详解.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:_5_UI详解"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>

    </Grid>
</Window>

运行:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值