WPF 基础 - 控件与布局

1. 前言

1. 数据驱动 UI

WPF 是数据核心、主动的,UI 从属数据并表达数据、是被动的;
不再是 UI 驱动数据,而是数据驱动 UI;

2. 控件的定义

控件、数据内容、行为(控件响应用户操作执行自己的方法或以事件的形式通知应用程序);
1)控件是数据和行为的载体;
2)所以关注控件时应该关注抽象的数据和行为而不是具体的形象,
3)比如符合"能展示内容并相应用户单击"这一抽象概念的 UI 元素都可以是 Button,而具体的样子完全可以通过 Style 和 Template 决定,checkbox 也不是因为有个 box 可以 check 才叫 checkbox。

3. 控件类型

  1. 布局控件:Grid、StackPanel、DockPanel、WarpPanel 等 Panel 的子类;
  2. 内容控件:只能容纳一个其他控件或布局控件作为它的内容。如 Window、Button 等 ContentControl 的子类;
  3. 带标题的内容控件:GroupBox、TabItem 等 HeaderedContentControl 的子类;
  4. 条目控件:显示一列数据,一般这列数据之间的类型一致;ListBox、ComboBox 等 ItemsControl 的子类;
  5. 带标题的条目控件:TreeViewItem、MenuItem 等 HeaderedContentControl 的子类;
<TreeView>
    <TreeViewItem Header="A">
        <TreeViewItem Header="A1">A11</TreeViewItem>
    </TreeViewItem>
    <TreeViewItem Header="B">
        <TreeViewItem Header="B1">B11</TreeViewItem>
    </TreeViewItem>
</TreeView>
 
<Menu>
    <MenuItem Header="菜单">
        <MenuItem Header="新建" InputGestureText="Ctrl+N">                     
            <MenuItem.Icon>
                <Image Source="/Images/2.png"/>
            </MenuItem.Icon>
            <MenuItem Header="设备" Click="MenuItem_Click"/>              
        </MenuItem>  
    </MenuItem>
    <MenuItem Header="设置" />
    <MenuItem Header="关于" />  
</Menu>
  1. 特殊内容控件:TextBox、TextBlock、Image
graph LR DependencyObject-->Dispatcher Visual-->DependencyObject UIElement-->Visual FrameworkElement-->UIElement Panel-->FrameworkElement Control-->FrameworkElement TextBlock-->FrameworkElement Image-->FrameworkElement ContentControl-->Control HeaderedContentControl-->ContentControl ItemsControl-->Control HeaderedItemsControl-->ItemsControl TextBox-->Control

2. 内容模型

2.1 逻辑树、可视元素树

可视树:因为 WPF 有Content 的概念,使控件与控件之间可以存在包含关系,以窗体为根,整个 WPF 的 UI 才形成树形结构。

2.2 内容属性

不同控件的内容属性名称不一:Content、Child、Items、Children、Text;
Button.Content、StackPanel.Children、ListBox.Items。

2.3 各类内容模型详解

2.3.1 ContentControl 族

  • 内容属性:Content
  • 常用:
    Button、Window、Label、UserControl、
    ListBoxItem、ListViewItem、ComboBoxItem、
    RadioButton、ToggleButton、CheckBox、
    ToolTip、ScrollViewer、ContentControl;
  • 不常用:
    ButtonBase、GroupItem、RepeatButton、StatusBarItem、NavigationWindow、Frame、GridViewColumnHeader

2.3.2 HeaderedContentControl

  • 内容属性:Content、Header
  • 常用:TabItem、Expander、HeaderedContentControl
  • 不常用:GroupBox

2.3.3 ItemsControl

  • 内容属性:Items 或 ItemsSource
    每种 ItemsControl 都对应有自己的条目容器 Item Container,如 ListBox 的 Item Container 是 ListBoxItem,关键词:包装机制
  • 常用:
    ListBox、ListView、ComboBox、Menu、ContextMenu、ItemsControl、TabControl、TreeView、StatusBar
  • 不常用:
    MenuBase、Selector(ListBox、ComboBox、TabControl 等的父类)
2.3.3.1 ListBox
  • DisplayMemberPath、SelectedValue、SelectedValuePath、SelectedItem、SelectedItems
ItemsContorl Item Container
ComboBox ComboBoxItem
ListBox ListBoxItem
ListView ListViewItem
TabControl TabItem
Menu MenuItem
ContextMenu MenuItem
TreeView TreeViewItem
StatusBar StatusBarItem

2.3.4 HeaderedItemsControl

内容属性:Items 或 ItemsSource、Header

常用:
MenuItem、TreeViewItem、ToolBar

2.3.5 Decorator 族

  • 内容属性: Child
    起 UI 装饰作用
  • 常用:
    Border、ViewBox
  • 不常用:
    ButtonChrome、ListBoxChrome、BulletDecorator、InkPresenter、AdornerDecorator、ClassicBorderDecorator、SystemDropShadowChome

2.3.6 TextBox、TextBlock

2.3.7 Shape 族

  • Path、Polygon、Polyline 等 Shape 子类;
  • Stroke 设置边线、Fill 设置填充;
  • 无内容属性;
  • 用于 2D 图形绘制。
<Polygon Points="10,10 100,125 20,125" Stroke="Red"/>
<Polyline Points="10,10 100,125 20,125" Stroke="Red"/>
<Path Stroke="Red">
    <Path.Data>
        <PathGeometry Figures="M 10,100 C 10,300 300,-160 100,10"/>
    </Path.Data>
</Path>
<Path Data="M 12.37,87.5 A 15,15 0 0 0 60,115" Stroke="Red" />

Path:
起点命令 M,终点命令 Z(让头尾相连)
直线 L,水平直线 H,垂直直线 V,曲线 C、Q、S、T
椭圆 A

2.3.8 Panel 族

  • 内容属性:Children
  • 常用:
    Grid、StackPanel、DockPanel、WrapPanel、Canvas
  • 不常用:
    UniformGrid(Grid 简化版,定义几行几列,每个单元格大小一致)、TabPanel、ToolBarOverflowPanel、ToolBarPanel、VirtualizingPanel、VirtualizingStackPanel
2.3.8.1 Grid
  • Grid 共享尺寸属性 SharedSizeGroup 运用:
    1)将父级 Grid 的 Grid.IsSharedSizeScope 设置为 true;
    2)两个 Grid 各自某一行或某一列的 SharedSizeGroup 设置为同一个字符串,那么这两行或这两列就可以共享空间。
<Grid Grid.IsSharedSizeScope="True">
    <Grid x:Name="layer0Grid"
        Panel.ZIndex="0"
        MouseEnter="layer0Grid_MouseEnter">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        ...
    </Grid>

    <Grid x:Name="toolboxLayerGrid" Visibility="Collapsed">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" SharedSizeGroup="ToolboxGroup" />
        </Grid.ColumnDefinitions>

        <GridSplitter Grid.Column="1" Width="3" HorizontalAlignment="Left" />
        <Grid x:Name="toolboxGrid" Grid.Column="1" Margin="3,0,0,0">
        </Grid>
    </Grid>
</Grid>

toolboxLayerGrid.Visibility = System.Windows.Visibility.Visible;
toolboxLayerGrid.SetValue(Grid.ZIndexProperty, 2);
layer0Grid.ColumnDefinitions.Add(new ColumnDefinition { SharedSizeGroup = "ToolboxGroup" });
  • Grid 宽高接受的尺寸单位:Pixel(像素,默认单位)、Inch(英寸=96 piexl)、Centimeter(厘米=96/2.54 pixel)、Point(=96/72 pixel)
  • 如果把两个元素放在 Grid 的同一个单元格内,则后书写的元素将在先书写的元素之上,可以通过 Panel.ZIndex 值调整,值越大,越靠上。默认为 1.
2.3.8.2 StackPanel
  • Orientation 决定横向排列还是纵向排列;
  • 布局风格:垒积木
2.3.8.3 Canvas
  • Canvas.Top 、Canvas.Left;
  • 用于基本不改动、艺术性比较强、需要大量使用横坐标作为绝对定位、依赖横坐标的动画等场景;
  • 两个元素占据同一个位置时,跟 Grid 一样。
2.3.8.4 DockPanel
  • LastChildFill
2.3.8.5 WrapPanel
  • 流式布局,Orientation 默认 Horizontal:从左到右 从上到下。
posted @ 2021-02-23 22:54  鑫茂  阅读(235)  评论(0编辑  收藏  举报