emmm,Winform相关的视频还没看完,在纠结要不要继续开新的内容,但是自我感觉,Winform真的没什么东西,而且也大多都过时了,哎,而且自己手头也有一套朝夕教育的试学版本内容,和喜课堂的VIP课程,emmm,以哪个为准呢?朝夕教育里面的视频,都在讲解每个控件的内容,没什么深度。最好的办法,就是找个大块时间,集中吧那些视频集体刷一遍。
每次面临选择的时候都好纠结,怎么办呢,其实还是自己太懒了,导致自己面临时间有限,能利用的事件不多的境况。要调整好自己的状态,每天学习的事件多一点,最主要的是脑子动起来,不能狗熊掰棒子,嗯!!!
本内容是对朝夕教育-WPF+上位机+工业互联_愚公搬代码的博客-CSDN博客这一系列文章的简单整理,具体整理多少根据这一周的情况再具体定吧。
桌面应用开发思维转变
常见的桌面应用的框架:Java框架、.NET 框架、Electron框架、QT框架。
- Java框架:Java桌面应用程序可以使用JavaFX或Swing框架。JavaFX提供了一个现代化的图形用户界面和矢量图形操作,而Swing则提供了一个传统的图形用户界面和大量的组件类库。
- .NET框架:.NET桌面应用程序主要使用Windows Forms或WPF框架。Windows Forms提供基于Win32API的GUI控件,而WPF提供了更现代、更灵活的GUI控件和可扩展性。
- Electron框架:Electron桌面应用程序使用JavaScript、HTML和CSS开发,可以让开发者使用Web技术开发出本地应用程序并在不同平台上运行。
- QT框架:QT桌面应用程序使用C++编写,提供了一套丰富的GUI组件库和一些便于跨平台开发的工具。
WPF 的 源码再Github上:https://github.com/dotnet/wpf
WPF(Windows Presentation Foundation)基于 .Net Framework的桌面应用程序界面设计框架,能够使用XMAL语言创建高质量的富有交互性的Windows客户端应用程序界面,同时还支持通过数据绑定实现界面与数据的分离,提高了程序开发的效率和可维护性。
使用场景包括
桌面应用程序的开发、数据可视化、游戏界面设计、内部管理系统、独立应用程序
- 桌面应用程序的开发:WPF提供了丰富的控件库和可自定义样式的界面设计语言,能够帮助开发者快速构建富有交互性的、美观的桌面应用程序。
- 数据可视化:WPF支持数据绑定,能够将数据直接绑定到UI元素上,实现数据的实时展示和交互操作,因此在数据可视化方面应用广泛。
- 游戏界面设计:WPF提供了支持3D渲染的工具和控件,能够帮助游戏开发者实现游戏的界面设计和效果展示。
- 内部管理系统:企业内部管理系统往往需要高度定制化的界面,WPF能够帮助企业开发者快速构建满足特定需求的管理系统。
- 独立应用程序:WPF可以帮助开发者将应用程序打包成独立的可执行文件,方便用户下载和部署。
如何渲染的
使用 DirectX 作为其界面渲染引擎,支持3D效果。使用矢量图形来绘制界面,而不是像素图形(矢量缩放不失真、占用文件小、可编辑能力强、渲染较慢)。还支持硬件加速,大大提高界面的渲染性能
渲染和逻辑处理是分离的,WPF将UI控件和逻辑处理分别封装在不同的类中,可自由组合这些类。通过这种方式,开发人员可以实现高度可定制化的界面,同时保持逻辑处理的清晰和简洁。还允许WPF应用陈鼓型在不同的线程上并行执行逻辑处理和界面渲染,从而提高了应用程序的性能和响应速度没此外还是得WPF的应用程序额可以更容易的实现MVVM模式和测试驱动开发(TDD)。
WPF的体系结构
使用XAML 语言来进行界面设计,并通过 .NET 中的代码与界面进行交互。
WPF的体系结构如下:
- <p>应用程序:WPF 应用程序是基于 .NET 框架的应用程序,集成了 WPF 的功能模块和组件,提供了一个界面来与用户交互。</p>
- <p>用户界面:WPF 用户界面是用 XAML 定义的,它包含了窗口、控件、布局和样式等元素。
- <p>窗口:WPF 窗口是用于承载用户界面的容器,除了标准的窗口外,还有可以自定义、透明、无边框等不同类型的窗口。</p>
- <p>控件:WPF 中提供了大量的控件,包括文本框、按钮、菜单、列表框等,这些控件可以用于构建用户界面。</p>
- <p>布局:WPF 中提供了多种布局方式,例如 Grid、StackPanel、WrapPanel 等,可以用于管理和排列控件。</p>
- <p>样式:WPF 的样式和模板是用来定义控件的外观和行为的,可以提供整个应用程序的一致性外观。</p>
- <p>事件:WPF 的事件模型非常强大,可以使开发人员轻松地订阅和处理事件。</p>
- <p>数据绑定:WPF 中的数据绑定允许开发人员将数据与界面元素进行关联,从而实现 UI 的自动更新和更高效的开发。</p>
- <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的布局处理是通过一组布局管理器来实现的。以下是常用的布局管理器:
- StackPanel:按照方向(横向或纵向)依次排列控件。
- Grid:使用行和列来定义网格,并放置控件。
- Canvas:使用绝对位置来定位控件。
- WrapPanel:类似于StackPanel,但是会自动换行。
- DockPanel:将控件停靠在父容器的边缘或中心。
上面的这些布局管理器可以嵌套使用,以实现复杂的布局。例如,将一个Grid放置在StackPanel中,可以实现在垂直方向上排列多个网格。
除了布局管理器外,WPF还提供了一些附加属性来帮助控件进行布局,例如Margin、HorizontalAlignment和VerticalAlignment等。这些属性可以在XAML中设置,也可以在代码中动态设置。WPF的布局处理是通过一组布局管理器来实现的。
无边框设计
不使用传统的窗口边框和标题栏来装饰应用程序窗口,而是完全自定义应用程序的外观和交互行为,可以让开发人员更加自由地创造独特的用户界面,同时也提供了更好的性能和可扩展性。
-
自定义窗口边框和标题栏样式,包括大小、形状、颜色和文本样式等。
-
使用特定的控件来实现窗口的最小化、最大化和关闭等操作,以取代传统的窗口按钮。
-
使用动画和效果来增强交互体验,例如在鼠标悬停时显示工具提示、在窗口拖动时使用缓动效果等。
-
使用特定的布局控件和容器来实现窗口内容的自适应和响应式布局。
下面是一个无边框设计的代码
<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
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>
布局原则
-
使用布局容器:WPF提供了多种布局容器,如Grid、StackPanel、Canvas等,可以根据布局要求选择相应的容器。
-
使用组件对齐:在WPF中,组件可以使用HorizontalAlignment和VerticalAlignment属性控制水平和垂直方向的对齐方式。
-
使用网格布局:使用Grid布局可以将UI元素放置在网格中,方便调整和组织。
-
使用大小调整:WPF提供了多种方式调整组件的大小,如使用Margin、Padding、Width和Height等属性。
-
使用自动布局:WPF中的布局系统可以自动适应组件的大小和位置,避免了手动计算和布局。
-
使用样式和模板:WPF中的样式和模板可以将UI元素的布局、样式和行为进行统一管理,提高了布局的灵活性和可维护性。
布局过程
-
测量(Measure):这一步是为了计算控件的大小,确定其需要的空间。该过程中,从父级容器中获取约束(Constraint),如宽度和高度。
-
安排(Arrange):根据计算出来的大小和约束,确定控件的位置。这一步是通过设置控件的位置和大小来实现的。
-
渲染(Render):在布局完成后,将控件绘制到屏幕上。
-
更新(Update):布局过程中,如果属性发生了改变,需要重新进行布局。比如,控件的内容或者大小发生变化。
WPF布局系统提供一些附加的服务,如测量工作的缓存,用于提高性能,以及支持控件的自定义测量和排列。除了常规的布局处理之外,WPF还提供了数据绑定、动画和模板等高级特性,可以让控件的布局更加灵活和易于维护。
布局控件
Grid控件
它可以将控件按照网格的形式排列,并可以设置行、列、单元格的属性,比如宽度、高度、对齐方式等。
在WPF中,Grid控件的布局属性主要有以下几种:
-
RowDefinitions和ColumnDefinitions:分别定义网格中的行和列,可以设置行高和列宽。
-
Grid.Row和Grid.Column:用来指定控件所在的行和列。可以设置控件所占据的行数和列数。
-
Grid.RowSpan和Grid.ColumnSpan:用来指定控件跨越的行数和列数。
-
HorizontalAlignment和VerticalAlignment:用来指定控件在单元格中的水平和垂直对齐方式。
-
Margin:用来指定控件与单元格边缘的距离。
-
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控件的常用属性如下:
-
Orientation:取值为“Horizontal”(水平方向排列)或“Vertical”(垂直方向排列)。
-
HorizontalAlignment和VerticalAlignment:用于控制子控件在StackPanel内的水平对齐方式和垂直对齐方式。
-
Margin:用于控制StackPanel控件的边距。
-
Background:用于设置StackPanel控件的背景颜色。
-
MinHeight和MinWidth:用于控制StackPanel控件的最小高度和宽度。
-
MaxHeight和MaxWidth:用于控制StackPanel控件的最大高度和宽度。
-
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控件的常用属性如下:
- Dock:指定控件在DockPanel中的停靠方式,值为Left、Top、Right、Bottom或None,默认值为Left。
- LastChildFill:当DockPanel中有多个控件时,指定最后一个控件是否填充剩余空间,默认值为True。
- Background:指定控件的背景色。
- Margin:指定控件与其他控件之间的空白边距。
- Padding:指定内容与控件边缘之间的空白边距。
- HorizontalAlignment:指定控件在水平方向上的对齐方式,值为Left、Center、Right或Stretch,默认值为Stretch。
- VerticalAlignment:指定控件在垂直方向上的对齐方式,值为Top、Center、Bottom或Stretch,默认值为Stretch。
- Width:指定控件的宽度。
- Height:指定控件的高度。
- MinWidth:指定控件的最小宽度。
- MinHeight:指定控件的最小高度。
- MaxWidth:指定控件的最大宽度。
- 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控件的主要属性如下:
-
Orientation:指定子元素的排列方向,可以是水平(Horizontal)或垂直(Vertical),默认为水平方向。
-
ItemWidth:指定子元素的宽度,如果未指定,则使用子元素的默认宽度。
-
ItemHeight:指定子元素的高度,如果未指定,则使用子元素的默认高度。
-
ItemMargin:指定子元素之间的间隔大小,默认为0。
-
HorizontalAlignment:指定子元素的水平对齐方式,可以是左对齐(Left)、居中对齐(Center)或右对齐(Right),默认为左对齐。
-
VerticalAlignment:指定子元素的垂直对齐方式,可以是上对齐(Top)、居中对齐(Center)或下对齐(Bottom),默认为上对齐。
-
FlowDirection:指定子元素的排列顺序,可以是从左到右(LeftToRight)或从右到左(RightToLeft),默认为从左到右。
-
CanHorizontallyScroll:指定是否可以水平滚动。
-
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控件有以下属性:
-
Rows:指定UniformGrid控件中的行数。
-
Columns:指定UniformGrid控件中的列数。
-
FirstColumn:指定第一个子控件应该位于哪一列。
-
FirstRow:指定第一个子控件应该位于哪一行。
-
HorizontalAlignment:指定UniformGrid控件中所有子控件的水平对齐方式。
-
VerticalAlignment:指定UniformGrid控件中所有子控件的垂直对齐方式。
-
Margin:指定UniformGrid控件与其父控件之间的边距。
-
Background:指定UniformGrid控件的背景颜色或背景图片。
-
Padding:指定UniformGrid控件中所有子控件之间的间距大小。
-
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控件属性包括:
- Background:设置Canvas的背景颜色或使用图片进行填充
- Width和Height:设置Canvas的宽度和高度
- Children:用于添加子元素,可以添加任何UIElement对象
- ClipToBounds:指定Canvas是否截取超出其边界的子元素
- IsItemsHost:指定Canvas是否作为ItemsControl子控件的宿主控件
- Left、Top、Right、Bottom:确定子元素的位置和大小,可以使用Canvas.SetXXX方法进行设置
- RenderTransform:应用于Canvas的变换效果,可以包括旋转、缩放和平移等操作
- 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中用于手写或涂鸦的控件,它具有以下属性:
-
Background:设置InkCanvas的背景颜色或背景图像。
-
DefaultDrawingAttributes:设置InkCanvas默认的画笔属性,如颜色、粗细等。
-
EditingMode:设置InkCanvas的编辑模式,包括Ink、EraseByPoint、EraseByStroke等。
-
EditingModeInverted:设置InkCanvas的反向编辑模式,可以将之前的Ink转换为橡皮擦。
-
EraserShape:设置InkCanvas橡皮擦的形状,如矩形或圆形。
-
Strokes:获取或设置在InkCanvas上绘制的笔画。
-
DefaultStylusPointDescription:获取或设置InkCanvas默认的触笔点的描述,包括坐标、压力等信息。
-
UseCustomCursor:设置是否在InkCanvas上使用自定义光标。
-
Cursor:设置InkCanvas上的光标。
-
IsManipulationEnabled:设置是否允许手势操作。
-
IsHitTestVisible:设置是否允许在InkCanvas上进行命中测试。
-
GestureRecognizer:获取或设置手势识别器,用于识别手势操作。
-
DynamicRenderer:获取或设置用于在InkCanvas上实时呈现笔画的DynamicRenderer对象。
-
ActiveEditingMode:获取或设置当前InkCanvas的激活编辑模式,包括Ink、EraseByPoint、EraseByStroke等。
-
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控件属性有:
-
Background:设置Border控件背景色。
-
BorderBrush:设置Border控件边框的颜色。
-
BorderThickness:设置Border控件的边框宽度。
-
CornerRadius:设置Border控件的圆角半径。
-
Padding:控制Border控件内部内容与Border边缘之间的距离。
-
SnapsToDevicePixels:设置Border的渲染方式,使其在像素级别上对齐。
-
UseLayoutRounding:设置Border的渲染方式,使用布局舍入。
-
Effect:设置Border控件的效果,如阴影、模糊等。
-
Opacity:设置Border控件的透明度。
-
RenderTransform:设置Border控件的渲染变换。
-
VerticalAlignment、HorizontalAlignment:设置Border控件的垂直和水平对齐方式。
-
Visibility:设置Border控件的可见性。
-
Name:设置Border控件的名称,以便在代码中引用。
-
Tag:设置Border控件的标记,以便在代码中识别。
-
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>