Dean的周学习内容:24.4.29~5.12(因为有五一假期啊)WPF 相关的基础知识

emmm,Winform相关的视频还没看完,在纠结要不要继续开新的内容,但是自我感觉,Winform真的没什么东西,而且也大多都过时了,哎,而且自己手头也有一套朝夕教育的试学版本内容,和喜课堂的VIP课程,emmm,以哪个为准呢?朝夕教育里面的视频,都在讲解每个控件的内容,没什么深度。最好的办法,就是找个大块时间,集中吧那些视频集体刷一遍。

每次面临选择的时候都好纠结,怎么办呢,其实还是自己太懒了,导致自己面临时间有限,能利用的事件不多的境况。要调整好自己的状态,每天学习的事件多一点,最主要的是脑子动起来,不能狗熊掰棒子,嗯!!!

本内容是对朝夕教育-WPF+上位机+工业互联_愚公搬代码的博客-CSDN博客这一系列文章的简单整理,具体整理多少根据这一周的情况再具体定吧。

桌面应用开发思维转变

常见的桌面应用的框架:Java框架、.NET 框架、Electron框架、QT框架。

  1. Java框架:Java桌面应用程序可以使用JavaFX或Swing框架。JavaFX提供了一个现代化的图形用户界面和矢量图形操作,而Swing则提供了一个传统的图形用户界面和大量的组件类库。
  2. .NET框架:.NET桌面应用程序主要使用Windows Forms或WPF框架。Windows Forms提供基于Win32API的GUI控件,而WPF提供了更现代、更灵活的GUI控件和可扩展性。
  3. Electron框架:Electron桌面应用程序使用JavaScript、HTML和CSS开发,可以让开发者使用Web技术开发出本地应用程序并在不同平台上运行。
  4. QT框架:QT桌面应用程序使用C++编写,提供了一套丰富的GUI组件库和一些便于跨平台开发的工具。

WPF 的 源码再Github上:https://github.com/dotnet/wpf

WPF(Windows Presentation Foundation)基于 .Net Framework的桌面应用程序界面设计框架,能够使用XMAL语言创建高质量的富有交互性的Windows客户端应用程序界面,同时还支持通过数据绑定实现界面与数据的分离,提高了程序开发的效率和可维护性。

使用场景包括

桌面应用程序的开发、数据可视化、游戏界面设计、内部管理系统、独立应用程序

  1. 桌面应用程序的开发:WPF提供了丰富的控件库和可自定义样式的界面设计语言,能够帮助开发者快速构建富有交互性的、美观的桌面应用程序。
  2. 数据可视化:WPF支持数据绑定,能够将数据直接绑定到UI元素上,实现数据的实时展示和交互操作,因此在数据可视化方面应用广泛。
  3. 游戏界面设计:WPF提供了支持3D渲染的工具和控件,能够帮助游戏开发者实现游戏的界面设计和效果展示。
  4. 内部管理系统:企业内部管理系统往往需要高度定制化的界面,WPF能够帮助企业开发者快速构建满足特定需求的管理系统。
  5. 独立应用程序:WPF可以帮助开发者将应用程序打包成独立的可执行文件,方便用户下载和部署。

如何渲染的

使用 DirectX 作为其界面渲染引擎,支持3D效果。使用矢量图形来绘制界面,而不是像素图形(矢量缩放不失真、占用文件小、可编辑能力强、渲染较慢)。还支持硬件加速,大大提高界面的渲染性能

渲染和逻辑处理是分离的,WPF将UI控件和逻辑处理分别封装在不同的类中,可自由组合这些类。通过这种方式,开发人员可以实现高度可定制化的界面,同时保持逻辑处理的清晰和简洁。还允许WPF应用陈鼓型在不同的线程上并行执行逻辑处理和界面渲染,从而提高了应用程序的性能和响应速度没此外还是得WPF的应用程序额可以更容易的实现MVVM模式和测试驱动开发(TDD)。

WPF的体系结构

使用XAML 语言来进行界面设计,并通过 .NET 中的代码与界面进行交互。

WPF的体系结构如下:

  1. <p>应用程序:WPF 应用程序是基于 .NET 框架的应用程序,集成了 WPF 的功能模块和组件,提供了一个界面来与用户交互。</p>
  2. <p>用户界面:WPF 用户界面是用 XAML 定义的,它包含了窗口、控件、布局和样式等元素。
  3. <p>窗口:WPF 窗口是用于承载用户界面的容器,除了标准的窗口外,还有可以自定义、透明、无边框等不同类型的窗口。</p>
  4. <p>控件:WPF 中提供了大量的控件,包括文本框、按钮、菜单、列表框等,这些控件可以用于构建用户界面。</p>
  5. <p>布局:WPF 中提供了多种布局方式,例如 Grid、StackPanel、WrapPanel 等,可以用于管理和排列控件。</p>
  6. <p>样式:WPF 的样式和模板是用来定义控件的外观和行为的,可以提供整个应用程序的一致性外观。</p>
  7. <p>事件:WPF 的事件模型非常强大,可以使开发人员轻松地订阅和处理事件。</p>
  8. <p>数据绑定:WPF 中的数据绑定允许开发人员将数据与界面元素进行关联,从而实现 UI 的自动更新和更高效的开发。</p>
  9. <p>图形和动画:WPF 中的图形和动画支持矢量图形、3D 图形和高级动画等,可以用于创建复杂的可视化效果。</p>

三层体系结构

Presentation Framework:用于在WPF开发中,开发图形的用户界面(GUI)库

Presentation Core:一个库,为开发WPF应用名陈鼓型提供核心服务,如,渲染、输入、媒体服务等。

Windows Base:一个库。提供应用程序基本的操作系统服务

mllCore:在基于Windows的应用程序中提供多媒体相关的服务库,例如媒体文件的解码和播放

WindowsCodecs:一个库,为基于Windows的应用程序中的图像和文件格式提供支持

Direct3D:一种图形API,用于在基于Windows的应用程序中开发3D图形应用程序

User32: 在基于Windows的应用程序中提供低级用户界面服务的库,如窗口管理、消息传递和输入处理

基本控件集合类

DispatcherObject:一个对象,有一个与WPF线程相关联的Dispacther,可用于将操作放入适当的线程上下文中执行。

Dependency Object:一个基类,提供了依赖属性的支持,是对象能够与应用恒旭中的其他对象进行数据绑定

Visual:一种类型的对象,便是WPF终端可视元素,如图形、文本、multmedia

UIElement:表示可视元素的基类,可通过它接受输入、处理命令、渲染和布局

Framework Element:是UIElement的子类,增加了数据绑定、样式、模板、布局和其他功能

Shape:表示可渲染的图形元素、如直线、矩形、椭圆和路径

Control:表示可包含可视化内容的基本控件,如Button、TextBox、CheckBox等

Content Control:表示具有单个可视化子元素的控件,如Label、Button等

Items Control:表示具有可多次重复的子元素的控件、如ListBox、TabControl、TreeView等、

Panel:将子元素按照特定的布局进行排列的控件,如StackPanel、Grid、DockPanel等

下面这张图表示不同类之间的关系,我记得好像有更详细的讲解的地方:入门 - WPF中文网 - 从小白到大佬 (wpfsoft.com)这个地方详细讲解了每个类的作用和功能

下面是一个简单的代码

<Window x:Class="Zhaoxi.WPFStudy.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:Zhaoxi.WPFStudy"
        mc:Ignorable="d" FontSize="30"
        Title="{Binding Title}" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <TextBox Height="30" VerticalAlignment="Top" Background="Orange" Margin="10"
                 Text="{Binding TB1Model.Text,UpdateSourceTrigger=PropertyChanged}" TextChanged="TextBox_TextChanged"/>
            <TextBox Height="30" VerticalAlignment="Top" Margin="10"
                 Text="{Binding TB2Model.Text,UpdateSourceTrigger=PropertyChanged}"/>
        </StackPanel>
        <Button HorizontalAlignment="Left" 
                Margin="35,82,0,0"  Width="{Binding BModel.Width}"
                VerticalAlignment="Top" Command="{Binding ClickCommand}">
            <TextBlock Text="{Binding BModel.Text}"/>
        </Button>
    </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 Zhaoxi.WPFStudy
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.DataContext = new WindowViewModel();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 按钮的点击 
            // 移动到VM中去
            //this.tb.Text = "Hello WPF!";
            //this.tb.Foreground = Brushes.Red;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Zhaoxi.WPFStudy.Base;

namespace Zhaoxi.WPFStudy
{

    public class WindowViewModel
    {
        // 完全可以/   必须是属性
        public string Title { get; set; } = "Hello WPF";
        public TextBoxModel TB1Model { get; set; } = new TextBoxModel();
        public TextBoxModel TB2Model { get; set; } = new TextBoxModel();
        public ButtonModel BModel { get; set; } = new ButtonModel();


        //业务逻辑
        // 需要绑定给界面的命令属性
        // VM中的方法也可以绑定
        public CommandBase ClickCommand
        {
            get => new CommandBase(DoClick);
        }
        // 该命令所执行的逻辑
        private void DoClick(object obj)
        {
            // 界面上两个输入
            // 进行计算逻辑  1+2=3

            Task.Run(async () =>
            {
                while (true)
                {
                    await Task.Delay(10);
                    // this.控件.text    线程
                    // 基本属性绑定没有跨线程
                    //BModel.Text = TB1Model.Text + TB2Model.Text;
                    // UI线程中处理   影响界面的刷新

                    BModel.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                }
            });
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Zhaoxi.WPFStudy
{
    public class TextBoxModel
    {
        public string Text { get; set; } = "Zhaoxi Jovan";
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Zhaoxi.WPFStudy
{
    public class ButtonModel : INotifyPropertyChanged 
    {
        // alt + enter
        public event PropertyChangedEventHandler PropertyChanged;
        public int Width { get; set; } = 400;
        //public string Text { get; set; } = "点击";

        private string _text = "点击";


        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Text"));
            }
        }

    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Zhaoxi.WPFStudy.Base
{
    public class CommandBase : ICommand
    {
        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            DoExecute?.Invoke(parameter);
        }

        public Action<object> DoExecute { get; set; }

        public CommandBase(Action<object> doExecute)
        {
            DoExecute = doExecute;
        }
    }
}

Telerik UI for WPF

提供了许多可定制的UI控件和功能,提供了一系列工具和技术,增强WPF应用程序的性能和稳定性。

Telerik UI for WPF – Telerik|KendoUI中文网

002-WPF布局控件

控件功能
Canvas用于绝对定位元素,可以直接指定元素相对于父元素或Canvas左上角的位置和大小。
DockPanel用于将元素分配到面板的上下、左右、中心位置,元素的大小可以自动调整。
Grid用于将元素分配到网格中,可以自由定义行和列,可实现复杂的布局。
StackPanel用于将元素按照方向堆叠排列,可以实现水平或垂直排列。
WrapPanel用于将元素按照方向排列,当一行或一列排不下时自动换行或换列。
UniformGrid用于将元素均匀分配到网格中,行列的大小相等。
VirtualizingStackPanel用于在大量数据的列表中进行虚拟化处理,提高性能。
ScrollViewer用于将元素放入滚动容器中,当元素大小超出容器大小时自动出现滚动条。
ItemContainerTemplate用于自定义可重复使用元素的外观和行为。
TabControl用于创建选项卡界面,可以切换不同的内容。
ToolBar用于显示一组工具按钮,可以在工具栏上方或下方放置其他控件。
ToolBarTray用于将多个ToolBar放入一个水平或垂直的容器中。
TreeView用于显示层次结构数据的树形列表。
Expander用于在界面中展开或收起额外的内容。
GroupBox用于将内容分组并添加标题,可以折叠展开。
ListBox用于显示一组列表项,并允许用户从中选择一个或多个。
ListView用于显示列表数据,可以自定义列和样式。
Menu用于创建菜单和子菜单。
Tootip用于显示提示信息。
ComboBox用于显示一个下拉列表,用户可以从中选择一个值。
StatusBar用于显示状态信息,通常位于窗口底部。
ScrollBar用于控制滚动容器中元素的可见部分。
Slider用于选择数值范围的控件。
ProgressBar用于显示进度条。
Separator用于在工具栏和菜单中分隔不同的项。
ContentControl可以显示任何类型的内容,并允许进行自定义。
Panel作为控件容器的基类。
Border用于在控件周围添加边框。
ViewBox可以自动缩放其内容以适应可用空间。
HeaderedContentControl带有标题的ContentControl。
HeaderedItemsControl带有标题的ItemsControl。
ItemsControl用于显示一组可重复使用的元素。
Calendar用于显示日期和日历。
DatePicker用于选择日期。
TimePicker用于选择时间。
DataGrid用于显示大量数据的表格。
DataTemplate用于自定义数据绑定的模板。
DataTrigger用于在数据绑定值更改时触发特定视觉效果。
MultiBinding允许将多个绑定合并到一个属性上。
CommandBinding用于将UI元素上的命令与应用程序逻辑绑定。
Style用于定义控件的视觉样式。
ControlTemplate用于自定义控件的外观和行为。
ResourceDictionary用于组织和管理资源。
VisualStateManager用于管理不同UI状态下的控件的视觉效果。
EventTrigger用于在某个事件发生时触发特定的视觉效果。
Binding用于将控件属性绑定到数据源。
RelativeSource用于在数据绑定中引用相对于目标控件的其他控件。
TemplateBinding用于将控件模板中的属性绑定到控件本身的属性。
Converter用于在数据绑定中将值从一种类型转换为另一种类型。
ValidationRule用于验证数据绑定的输入。

 WPF控件布局

这边布局只是讲几个案例,具体布局使用可以看WPF控件专题

WPF的布局处理是通过一组布局管理器来实现的。以下是常用的布局管理器:

  1. StackPanel:按照方向(横向或纵向)依次排列控件。
  2. Grid:使用行和列来定义网格,并放置控件。
  3. Canvas:使用绝对位置来定位控件。
  4. WrapPanel:类似于StackPanel,但是会自动换行。
  5. DockPanel:将控件停靠在父容器的边缘或中心。

上面的这些布局管理器可以嵌套使用,以实现复杂的布局。例如,将一个Grid放置在StackPanel中,可以实现在垂直方向上排列多个网格。

除了布局管理器外,WPF还提供了一些附加属性来帮助控件进行布局,例如Margin、HorizontalAlignment和VerticalAlignment等。这些属性可以在XAML中设置,也可以在代码中动态设置。WPF的布局处理是通过一组布局管理器来实现的。

无边框设计

不使用传统的窗口边框和标题栏来装饰应用程序窗口,而是完全自定义应用程序的外观和交互行为,可以让开发人员更加自由地创造独特的用户界面,同时也提供了更好的性能和可扩展性。

  1. 自定义窗口边框和标题栏样式,包括大小、形状、颜色和文本样式等。

  2. 使用特定的控件来实现窗口的最小化、最大化和关闭等操作,以取代传统的窗口按钮。

  3. 使用动画和效果来增强交互体验,例如在鼠标悬停时显示工具提示、在窗口拖动时使用缓动效果等。

  4. 使用特定的布局控件和容器来实现窗口内容的自适应和响应式布局。

下面是一个无边框设计的代码

<Window x:Class="Zhaoxi.LayoutStudy.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:Zhaoxi.LayoutStudy"
        mc:Ignorable="d"
        Title="MainWindow" Width="400" FontSize="16"
        SizeToContent ="Height"
        WindowStartupLocation="CenterScreen"
        WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <!--<Window.Clip>
        <RectangleGeometry Rect="20,20,100,50"/>
        <EllipseGeometry RadiusX="80" RadiusY="40" Center="50,50"/>
        <PathGeometry Figures="M117.5,0.66 C124.57615,-28.287894 109.76686,-39.946743 147,-54.84 167.67902,-63.11161 185.9579,-61.293286 208.5,-52.84 222.32639,-47.655105 233.42911,-43.807096 245,-34.34 253.06664,-27.740025 261.84249,-24.010334 267,-14.34 274.10567,-1.0168648 279.5,10.144515 279.5,26.16 279.5,35.339615 270.48945,38.672311 264.5,45.66 257.91477,53.342767 251.25906,60.649938 244.5,68.16 235.8575,77.762779 228.24856,80.285144&#xD;&#xA;214.5,81.66 193.7326,83.73674 183.44174,81.357641 163.5,75.66 144.09912,70.11689 123.36349,65.609706 104.5,58.66 82.590544,50.588095 76.066167,51.245154 63.5,27.16 55.000033,10.868397 48.761808,12.017288 62,-7.84 68.126788,-17.030182 74.447764,-22.335982 87.5,-23.34 96.711428,-24.048571 109.98442,-9.5074671 119,-4.34"/>
    </Window.Clip>-->
    <Border Background="#EEE" Margin="5" CornerRadius="5">
        <Border.Effect>
            <DropShadowEffect ShadowDepth="0" Color="Gray" Direction="0" Opacity="0.3" BlurRadius="10"/>
        </Border.Effect>

        <Grid Margin="10">
            <Grid.RowDefinitions>
                <RowDefinition Height="40"/>
                <RowDefinition Height="40"/>
                <RowDefinition Height="40"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>

            <TextBlock Text="用户名" VerticalAlignment="Center" Margin="20,0,0,0"/>
            <TextBlock Text="密  码" VerticalAlignment="Center" Grid.Row="1"/>
            <Button Content="登  录" Height="30" Grid.Row="2"/>
            <TextBlock Text="用户名或密码错误!" Foreground="Red" Grid.Row="3" VerticalAlignment="Center"
                   HorizontalAlignment="Center" Margin="0,10" Name="txtErrorMsg" Visibility="Collapsed"/>
        </Grid>
    </Border>
</Window>

布局原则

  1. 使用布局容器:WPF提供了多种布局容器,如Grid、StackPanel、Canvas等,可以根据布局要求选择相应的容器。

  2. 使用组件对齐:在WPF中,组件可以使用HorizontalAlignment和VerticalAlignment属性控制水平和垂直方向的对齐方式。

  3. 使用网格布局:使用Grid布局可以将UI元素放置在网格中,方便调整和组织。

  4. 使用大小调整:WPF提供了多种方式调整组件的大小,如使用Margin、Padding、Width和Height等属性。

  5. 使用自动布局:WPF中的布局系统可以自动适应组件的大小和位置,避免了手动计算和布局。

  6. 使用样式和模板:WPF中的样式和模板可以将UI元素的布局、样式和行为进行统一管理,提高了布局的灵活性和可维护性。

布局过程

  1. 测量(Measure):这一步是为了计算控件的大小,确定其需要的空间。该过程中,从父级容器中获取约束(Constraint),如宽度和高度。

  2. 安排(Arrange):根据计算出来的大小和约束,确定控件的位置。这一步是通过设置控件的位置和大小来实现的。

  3. 渲染(Render):在布局完成后,将控件绘制到屏幕上。

  4. 更新(Update):布局过程中,如果属性发生了改变,需要重新进行布局。比如,控件的内容或者大小发生变化。

 WPF布局系统提供一些附加的服务,如测量工作的缓存,用于提高性能,以及支持控件的自定义测量和排列。除了常规的布局处理之外,WPF还提供了数据绑定、动画和模板等高级特性,可以让控件的布局更加灵活和易于维护。

布局控件

Grid控件

它可以将控件按照网格的形式排列,并可以设置行、列、单元格的属性,比如宽度、高度、对齐方式等。

在WPF中,Grid控件的布局属性主要有以下几种:

  1. RowDefinitions和ColumnDefinitions:分别定义网格中的行和列,可以设置行高和列宽。

  2. Grid.Row和Grid.Column:用来指定控件所在的行和列。可以设置控件所占据的行数和列数。

  3. Grid.RowSpan和Grid.ColumnSpan:用来指定控件跨越的行数和列数。

  4. HorizontalAlignment和VerticalAlignment:用来指定控件在单元格中的水平和垂直对齐方式。

  5. Margin:用来指定控件与单元格边缘的距离。

  6. Padding:用来指定控件内边距。

示例代码:

<Grid>
   <Grid.RowDefinitions>
      <RowDefinition Height="50"/> <!--第一行高度为50-->
      <RowDefinition Height="Auto"/> <!--第二行高度自适应-->
   </Grid.RowDefinitions>
   <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/> <!--第一列宽度为剩余空间-->
      <ColumnDefinition Width="100"/> <!--第二列宽度为100-->
   </Grid.ColumnDefinitions>

   <Label Grid.Row="0" Grid.Column="0" Content="Row 1, Column 1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
   <Label Grid.Row="0" Grid.Column="1" Content="Row 1, Column 2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
   <Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="Row 2, Column 1-2" HorizontalAlignment="Center" VerticalAlignment="Center"
          Margin="5" Padding="10"/>
</Grid>

在这个示例中,我们定义了一个2x2的网格,第一行高度为50,第二行高度为自适应。第一列宽度为剩余空间,第二列宽度为100。在网格中放置了三个Label控件,第一个控件在第一行第一列,第二个控件在第一行第二列,第三个控件占据了第二行的全部列并设置了Margin和Padding。这个例子演示了Grid控件的基本使用方法和布局属性。

 

<Grid>
   <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
   </Grid.RowDefinitions>
   <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="Auto"/>
   </Grid.ColumnDefinitions>

   <!--第一行第二列-->
   <Label Grid.Row="0" Grid.Column="1" Content="Welcome to my app!" HorizontalAlignment="Center"/>

   <!--第二行第一列-->
   <Button Grid.Row="1" Grid.Column="0" Content="OK"/>
   <!--第二行第二列-->
   <Button Grid.Row="1" Grid.Column="1" Content="Cancel"/>
   <!--第二行第三列-->
   <Button Grid.Row="1" Grid.Column="2" Content="Exit"/>

   <!--第三行第一列-->
   <Label Grid.Row="2" Grid.Column="0" Content="© 2021 My Company, Inc."/>
   <!--第三行第二列-->
   <Label Grid.Row="2" Grid.Column="1"/>
   <!--第三行第三列-->
   <Label Grid.Row="2" Grid.Column="2"/>
</Grid>

在上面的这个例子中,我们定义了一个3x3的网格,第一行的Label通过设置HorizontalAlignment属性为Center实现了水平居中的效果。这个例子中还有一些留空的Label控件,它们可以用来占据网格中的空白部分,使布局更合理。

<Border BorderBrush="Green" BorderThickness="1" Margin="10 20 30 50">
    <Grid Grid.IsSharedSizeScope="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!--列头-->
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="50" SharedSizeGroup="A" />
                <ColumnDefinition Width="100" SharedSizeGroup="B"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Border Background="Orange"/>
            <Border Background="Green" Grid.Column="1" Margin="3,7,10,15"/>
            <!--左上右下-->
            <GridSplitter HorizontalAlignment="Right" Height="10" Width="5" Background="Gray"/>
            <GridSplitter HorizontalAlignment="Right" Height="10" Width="5" Background="Gray" Grid.Column="1"/>
        </Grid>

        <!--数据表-->
        <Grid Grid.Row="1" Height="60" VerticalAlignment="Top" Margin="0,10,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="A"/>
                <ColumnDefinition  SharedSizeGroup="B"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Border Background="Orange">
            </Border>
            <Border Grid.Column="1" BorderBrush="Red" BorderThickness="1">
                <TextBlock/>
            </Border>


        </Grid>
        <Grid Grid.Row="1" Height="30" VerticalAlignment="Top" Margin="0,150,0,0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition SharedSizeGroup="A"/>
                <ColumnDefinition  SharedSizeGroup="B"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Border Background="Orange">
            </Border>
            <Border Background="Green" Grid.Column="1"/>
        </Grid>

    </Grid>
</Border>

StackPanel控件

它允许您将控件排列在一行或一列中,并根据需要包装它们。StackPanel可以在水平或垂直方向上排列控件,并将控件压缩在可用空间内。StackPanel适用于需要动态添加或移除控件的情况,以及需要灵活地自动布局的情况

StackPanel控件的常用属性如下:

  1. Orientation:取值为“Horizontal”(水平方向排列)或“Vertical”(垂直方向排列)。

  2. HorizontalAlignment和VerticalAlignment:用于控制子控件在StackPanel内的水平对齐方式和垂直对齐方式。

  3. Margin:用于控制StackPanel控件的边距。

  4. Background:用于设置StackPanel控件的背景颜色。

  5. MinHeight和MinWidth:用于控制StackPanel控件的最小高度和宽度。

  6. MaxHeight和MaxWidth:用于控制StackPanel控件的最大高度和宽度。

  7. Children:用于向StackPanel控件中添加子控件。

水平排列的按钮

<StackPanel Orientation="Horizontal">
    <Button Content="按钮1"/>
    <Button Content="按钮2"/>
    <Button Content="按钮3"/>
</StackPanel>

垂直排列的文本框

<StackPanel Orientation="Vertical">
    <TextBox Text="文本框1"/>
    <TextBox Text="文本框2"/>
    <TextBox Text="文本框3"/>
</StackPanel>

多层嵌套

<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
    <!--栈-->
    <!--关于顺序问题:自定义布局的时候讲布局原理:StackPanel.Order="-1"-->
    <Border Background="Orange" Height="30" Width="50"/>
    <Border Background="Green" Height="30" Width="70" />
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="用户名:" VerticalAlignment="Center"/>
        <TextBox Width="100" Height="30"/>
    </StackPanel>
    <!--使用场景:ToolBar-》控件模板:-->
    <ToolBar Height="40">
        <Button Content="butt"/>
        <Button Content="butt"/>
        <Button Content="butt"/>
        <Button Content="butt"/>
    </ToolBar>
</StackPanel>

DockPanel

它可以使子元素根据指定的方向自动停靠在容器边缘,从而实现灵活的布局排列。通过设置子元素的DockPanel.Dock属性,子元素可以停靠在上、下、左、右四个方向中的任意一个或多个方向上。DockPanel控件通常用于实现窗口、工具栏等常见的用户界面组件的布局。

DockPanel控件的常用属性如下:

  1. Dock:指定控件在DockPanel中的停靠方式,值为Left、Top、Right、Bottom或None,默认值为Left。
  2. LastChildFill:当DockPanel中有多个控件时,指定最后一个控件是否填充剩余空间,默认值为True。
  3. Background:指定控件的背景色。
  4. Margin:指定控件与其他控件之间的空白边距。
  5. Padding:指定内容与控件边缘之间的空白边距。
  6. HorizontalAlignment:指定控件在水平方向上的对齐方式,值为Left、Center、Right或Stretch,默认值为Stretch。
  7. VerticalAlignment:指定控件在垂直方向上的对齐方式,值为Top、Center、Bottom或Stretch,默认值为Stretch。
  8. Width:指定控件的宽度。
  9. Height:指定控件的高度。
  10. MinWidth:指定控件的最小宽度。
  11. MinHeight:指定控件的最小高度。
  12. MaxWidth:指定控件的最大宽度。
  13. MaxHeight:指定控件的最大高度。
<DockPanel LastChildFill="True">
    <!--停靠-->
    <Button Content="Button2" DockPanel.Dock="Left"/>
    <Button Content="Button1" DockPanel.Dock="Top"/>
    <Button Content="Button4" DockPanel.Dock="Bottom"/><!--alt+箭头-->
    <Button Content="Button3" DockPanel.Dock="Right"/>
    <Button Content="Button5" DockPanel.Dock="Bottom"/>
    <Button Content="Button6"/>
</DockPanel>

WrapPanel

它可以自动把子元素按照指定方向排列,并在需要时自动换行。相比于其他面板控件,WrapPanel更加灵活,可以实现多种布局方式。在WrapPanel中,子元素可以具有不同的宽度和高度。它还可以控制子元素之间的间隔以及子元素的对齐方式。WrapPanel通常用于实现流式布局,例如显示文章列表、图片列表等。

WrapPanel控件的主要属性如下:

  1. Orientation:指定子元素的排列方向,可以是水平(Horizontal)或垂直(Vertical),默认为水平方向。

  2. ItemWidth:指定子元素的宽度,如果未指定,则使用子元素的默认宽度。

  3. ItemHeight:指定子元素的高度,如果未指定,则使用子元素的默认高度。

  4. ItemMargin:指定子元素之间的间隔大小,默认为0。

  5. HorizontalAlignment:指定子元素的水平对齐方式,可以是左对齐(Left)、居中对齐(Center)或右对齐(Right),默认为左对齐。

  6. VerticalAlignment:指定子元素的垂直对齐方式,可以是上对齐(Top)、居中对齐(Center)或下对齐(Bottom),默认为上对齐。

  7. FlowDirection:指定子元素的排列顺序,可以是从左到右(LeftToRight)或从右到左(RightToLeft),默认为从左到右。

  8. CanHorizontallyScroll:指定是否可以水平滚动。

  9. CanVerticallyScroll:指定是否可以垂直滚动。

<WrapPanel Orientation="Vertical">
    <Button Content="Button1" Height="40" Width="120" VerticalAlignment="Top"/>
    <Button Content="Button2" Height="40" Width="120" VerticalAlignment="Bottom"/>
    <Button Content="Button3" Height="60" Width="120"/>
    <Button Content="Button4" Height="40" Width="120"/>
    <Button Content="Button4" Height="80" Width="120"/>
    <Button Content="Button4" Height="40" Width="220"/>
    <Button Content="Button4" Height="40" Width="120"/>
    <Button Content="Button4" Height="40" Width="120"/>
    <Button Content="Button4" Height="40" Width="120"/>
    <Button Content="Button4" Height="40" Width="120"/>
    <Button Content="Button4" Height="40" Width="120"/>
</WrapPanel>

UniformGrid

UniformGrid控件是一种用于WPF和UWP应用程序中的布局控件,它将内容在一个均匀的网格中排列。UniformGrid控件提供了一种简单的方式来布局相同大小的元素,并且可以控制元素的行列数量。与其他布局控件相比,UniformGrid控件的优势在于它可以确保所有元素都具有相同的大小,并且不会影响布局中其他元素的位置

UniformGrid控件是一个布局面板,可以将其子控件排列成类似于网格的形式,其中每个子控件的大小和位置是相同的。UniformGrid控件有以下属性:

  1. Rows:指定UniformGrid控件中的行数。

  2. Columns:指定UniformGrid控件中的列数。

  3. FirstColumn:指定第一个子控件应该位于哪一列。

  4. FirstRow:指定第一个子控件应该位于哪一行。

  5. HorizontalAlignment:指定UniformGrid控件中所有子控件的水平对齐方式。

  6. VerticalAlignment:指定UniformGrid控件中所有子控件的垂直对齐方式。

  7. Margin:指定UniformGrid控件与其父控件之间的边距。

  8. Background:指定UniformGrid控件的背景颜色或背景图片。

  9. Padding:指定UniformGrid控件中所有子控件之间的间距大小。

  10. IsItemsHost:指定UniformGrid控件是否作为ItemsControl的ItemsPanel,并作为其子控件的容器。

<UniformGrid Rows="2" Columns="2">
    <Button Content="Button1"/>
    <Button Content="Button2"/>
    <Button Content="Button3"/>
    <Button Content="Button4"/>
    <Button Content="Button5"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
</UniformGrid>

Canvas

一个面板控件,用于在其上面放置其他控件或绘制图形。Canvas控件允许您以x,y坐标系的形式放置UI元素。您可以使用Canvas控件来创建自定义控件,或为您的应用程序中的其他控件提供布局支持。Canvas控件提供了许多附加属性,如Left,Top,Bottom和Right,用于定位和放置子元素。Canvas控件还允许您使用Path、Line、Polygon、Polyline等形状对象创建线条、多边形、折线等图形。

WPF中的Canvas控件属性包括:

  1. Background:设置Canvas的背景颜色或使用图片进行填充
  2. Width和Height:设置Canvas的宽度和高度
  3. Children:用于添加子元素,可以添加任何UIElement对象
  4. ClipToBounds:指定Canvas是否截取超出其边界的子元素
  5. IsItemsHost:指定Canvas是否作为ItemsControl子控件的宿主控件
  6. Left、Top、Right、Bottom:确定子元素的位置和大小,可以使用Canvas.SetXXX方法进行设置
  7. RenderTransform:应用于Canvas的变换效果,可以包括旋转、缩放和平移等操作
  8. Tag:一个Object类型的属性,用于存储任意数据,并与Canvas关联。
<Canvas>
        <Button Content="Button1" Width="300" Height="90"/>
        <Button Content="Button2" Canvas.Right="20" Canvas.Left="400" Canvas.Top="60" Canvas.Bottom="20"/>
    <Button Content="Button3" Panel.ZIndex="0"/>
    <Button Content="Button4" Panel.ZIndex="0"/>
    <Button Content="Button5" Width="250" Height="80"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Button6"/>
    <Button Content="Butt"/>
</Canvas>

InkCanvas

WPF中用于捕捉和显示用户手写笔迹的专用控件。它提供了一种可视化的方式来收集、编辑和呈现手写笔迹,可以用于绘图、手写笔记、签名等应用场景。InkCanvas控件提供了多种绘图工具和笔刷,可以自由选择颜色、笔触粗细和透明度等属性,同时还支持撤销、重做、清除、保存和加载笔迹等操作。InkCanvas控件还具有高度的可定制性,可以通过绑定事件、使用样式和自定义模板等方式实现个性化的界面和行为。

InkCanvas是WPF中用于手写或涂鸦的控件,它具有以下属性:

  1. Background:设置InkCanvas的背景颜色或背景图像。

  2. DefaultDrawingAttributes:设置InkCanvas默认的画笔属性,如颜色、粗细等。

  3. EditingMode:设置InkCanvas的编辑模式,包括Ink、EraseByPoint、EraseByStroke等。

  4. EditingModeInverted:设置InkCanvas的反向编辑模式,可以将之前的Ink转换为橡皮擦

  5. EraserShape:设置InkCanvas橡皮擦的形状,如矩形或圆形。

  6. Strokes:获取或设置在InkCanvas上绘制的笔画。

  7. DefaultStylusPointDescription:获取或设置InkCanvas默认的触笔点的描述,包括坐标、压力等信息。

  8. UseCustomCursor:设置是否在InkCanvas上使用自定义光标。

  9. Cursor:设置InkCanvas上的光标。

  10. IsManipulationEnabled:设置是否允许手势操作。

  11. IsHitTestVisible:设置是否允许在InkCanvas上进行命中测试。

  12. GestureRecognizer:获取或设置手势识别器,用于识别手势操作。

  13. DynamicRenderer:获取或设置用于在InkCanvas上实时呈现笔画的DynamicRenderer对象。

  14. ActiveEditingMode:获取或设置当前InkCanvas的激活编辑模式,包括Ink、EraseByPoint、EraseByStroke等。

  15. StylusPlugIns:获取或设置与InkCanvas一起使用的StylusPlugin对象集合。

<InkCanvas EditingMode="Ink" >
    <InkCanvas.DefaultDrawingAttributes>
        <DrawingAttributes Color="Red" Width="10" Height="10">
        </DrawingAttributes>
    </InkCanvas.DefaultDrawingAttributes>
    <Button Content="Button1" InkCanvas.Left="50" InkCanvas.Top="100"/>
    <Button Content="Button2"/>
    <Button Content="Button3"/>
    <Button Content="Button4"/>
    <Button Content="Button5"/>
    <Button Content="Button6"/>
    <Button Content="Button7"/>
    <Button Content="Button8"/>
    <Button Content="Button9"/>
</InkCanvas>

Border

用于将其他控件装入其中,并在它们周围添加边框、填充和背景。它可以显示一个矩形框,作为其他控件的容器,并可以通过控制边框颜色、样式和厚度来改变外观。Border控件还可以设置背景颜色和填充,以及圆角半径来实现更复杂的外观效果。Border控件常用于创建自定义控件、按钮、文本框、标签等UI元素

WPF中的Border控件属性有:

  1. Background:设置Border控件背景色。

  2. BorderBrush:设置Border控件边框的颜色。

  3. BorderThickness:设置Border控件的边框宽度。

  4. CornerRadius:设置Border控件的圆角半径。

  5. Padding:控制Border控件内部内容与Border边缘之间的距离。

  6. SnapsToDevicePixels:设置Border的渲染方式,使其在像素级别上对齐。

  7. UseLayoutRounding:设置Border的渲染方式,使用布局舍入。

  8. Effect:设置Border控件的效果,如阴影、模糊等。

  9. Opacity:设置Border控件的透明度。

  10. RenderTransform:设置Border控件的渲染变换。

  11. VerticalAlignment、HorizontalAlignment:设置Border控件的垂直和水平对齐方式。

  12. Visibility:设置Border控件的可见性。

  13. Name:设置Border控件的名称,以便在代码中引用。

  14. Tag:设置Border控件的标记,以便在代码中识别。

  15. ToolTip:设置Border控件的工具提示内容。

实例:在WPF中使用Border控件创建一个简单的登录窗口

下面是一个简单的WPF窗口,它使用Border控件实现了一个登录窗口。该窗口包含用户名和密码输入框、登录按钮和一个取消按钮。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Login Window" Height="200" Width="300">
    <Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5"
            Margin="10" Padding="5">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Label Grid.Row="0" Grid.Column="0" Content="Username:"/>
            <TextBox Grid.Row="0" Grid.Column="1" Margin="5" />
            <Label Grid.Row="1" Grid.Column="0" Content="Password:"/>
            <PasswordBox Grid.Row="1" Grid.Column="1" Margin="5" />
            <StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal"
                        HorizontalAlignment="Right" Margin="0,10,0,0">
                <Button Content="Cancel" Margin="5" IsCancel="True"/>
                <Button Content="Login" Margin="5" IsDefault="True"/>
            </StackPanel>
        </Grid>
    </Border>
</Window>

 自定义控件

public class ZxStackPanel : Panel
{
    // 从上向下的累积
    // 第一个子项  第一个
    // 第二个子项  在第一个子项的高度下面
    // 第三个子项  在第二个子项的高度+第一个子项的高度
    // 。。。。。

    // 两个过程:
    // 测量:
    // 排列

    List<ListItem> children = new List<ListItem>();
    // 测量:主要是对子控件进行期望尺寸的测量
    protected override Size MeasureOverride(Size availableSize)
    {
        //Size size = new Size(availableSize.Width / 4, availableSize.Height);
        // 记录所有子控件的整体高度
        double height = 0;
        // 遍历子控件,对控件一一进行测量动作
        foreach (FrameworkElement item in this.InternalChildren)
        {
            int index = ZxStackPanel.GetIndex(item);
            // 添加到临时集合,供后续排序用
            children.Add(new ListItem { Control = item, Index = index });
            // 控件测量->得到控件的期望尺寸DesiredSize
            item.Measure(availableSize);
            //
            height += item.DesiredSize.Height;
        }

        // 通过依赖附加属性对子控件进行排序
        children = children.OrderBy(c => c.Index).ToList();
        // 根据指定序号进行调整
        int i = 0;
        while (i < children.Count)
        {
            if (children[i].Index > 0)
            {
                ListItem item = children[i];
                children.RemoveAt(i);
                children.Insert(item.Index, item);
            }
            else
                i++;
        }

        // 返回所有子控件所需要的Size,可能比容器大小要大:availableSize
        return new Size(availableSize.Width, height);
    }

    // 排列:最终子控件在放在哪个位置(坐标)上
    // finalSize等于MeasureOverride返回值
    protected override Size ArrangeOverride(Size finalSize)
    {
        // 记录所有子控件的整体高度
        double height = 0;
        foreach (ListItem item in children)
        {
            // 将Item子项放到特定的位置 ,主要是在Rect的X和Y,大小由Rect的Width和Height决定
            item.Control.Arrange(new Rect(0, height, finalSize.Width, item.Control.DesiredSize.Height));
            //
            height += item.Control.DesiredSize.Height;
        }

        return finalSize;
    }


    // 需求:StackPanel中的子项进行顺序调整
    public static int GetIndex(DependencyObject obj)
    {
        return (int)obj.GetValue(IndexProperty);
    }

    public static void SetIndex(DependencyObject obj, int value)
    {
        obj.SetValue(IndexProperty, value);
    }
    public static readonly DependencyProperty IndexProperty =
        DependencyProperty.RegisterAttached("Index", typeof(int), typeof(ZxStackPanel), new PropertyMetadata(0));

    //private int _index;

    //public int Index
    //{
    //    get { return _index; }
    //    set { _index = value; }
    //}

    // 

    // 指定子项的区域大小  大中小
}

class ListItem
{
    public FrameworkElement Control { get; set; }
    public int Index { get; set; }
}

使用自定义的控件

<local:ZxStackPanel>
    <Button Content="Button1"/>
    <Button Content="Button2" local:ZxStackPanel.Index="5"/>
    <Button Content="Button3"/>
    <Button Content="Button4"/>
    <Button Content="Button5"/>
    <Button Content="Button6"/>
    <Button Content="Button7"/>
    <Button Content="Button8" local:ZxStackPanel.Index="3"/>
    <Border Background="Orange" Height="40"/>
</local:ZxStackPanel>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值