《深入浅出WPF》学习笔记

文章目录

  • 相关资源
  • 前言
  • WPF 学习笔记
    • 环境配置
    • WPF基础:一个WPF程序是如何启动的
      • xmal文件和cs文件是如何连接的
      • 如何确定启动页面
      • xmal文件如何引用别的文件
        • 如何引用
    • WPF是如何创建元素,改变元素的
      • WPF的元素创建和简单属性赋值
      • WPF的树形界面
      • Xmal属性赋值
        • 为什么要多种属性赋值
        • 属性转换
          • 解决方法
        • 属性标签
          • 属性标签的特点和缺点
          • 属性标签的缺点
        • 扩展标签
    • WPF的属性绑定
      • 页面元素相互赋值
      • WPF 数据绑定会在后面的Prism框架中进行详细说明。
    • WPF组件化

相关资源

《深入浅出WPF》系列高清视频教程 | 讲师:刘铁猛

深入浅出wpf pdf版完整版下载
刘铁猛老师B站号。但是只有最近的视频资料
在这里插入图片描述

前言

WPF 是一个设计非常超前的技术框架,即使他是在2007年开始研发,2010年正式发行的技术。里面的MVVM,业务代码和界面代码完全分离,低耦合,高内聚的思想一直影响着后来的前端发展。比如Vue就是MVVM的继承的。

WPF在国内就业市场的情况并不理想,原因是桌面软件的式微,功能逐渐从PC端转向WEB端。我用网页能解决的,为什么要下个客户端呢?WPF技术的推广也是个问题。因为传统互联网的崛起,把java抬到了一个非常高的高度,java的轮子特别多,生态特别好,学的人也特别多。

所以我认为,不要以为学了WPF就可以找到很好的工作了。.NET工程师还是要转全栈,前端后端都要会。我目前觉得最简单的全栈技术栈是Vue+uniapp+WPF+webApi+.NET core。数据库:Sql server sqlite Mysql。其实最好再学个Unity 2d+Unity 3d +C4D。这样就是完整的全栈了。基本一个简单的小项目你都可以解决。

我今年的模板就是学会WPF+Unity 2d+C4D建模。我学习的逻辑一直都是从低到高,就是先学会工具怎么用,再去钻研高深的东西。这部分学好了,明年就开始学linux和python。

C#和JAVA是相互竞争的关系,我暂时没有精力去学Java的知识。等我需要用到的时候再说吧

虽然有点离题了,回到深入浅出WPF ,刘铁猛老师还是很猛的,讲解的特别好。不像别的课,上来先讲个几个小时的控件属性。直接从原理开始讲,从底层到应用,特别的清晰。

WPF 学习笔记

视频资料地址

《深入浅出WPF》系列高清视频教程 | 讲师:刘铁猛

环境配置

  • .NET Core 6.0
  • WPF

在这里插入图片描述

WPF基础:一个WPF程序是如何启动的

我们创建的一个简单的WPF程序。
在这里插入图片描述

xmal文件和cs文件是如何连接的

WPF为了做到页面和业务分离,强制了我们只能在xmal里面写页面,在cs文件里面写业务。这个强制分离是为了降低耦合。如果有同学试过维护JQuery的项目就知道业务和页面不分离是多么痛苦的事情。一个函数里面包含了页面逻辑和业务逻辑,导致后期更改的时候要完全理解整个函数是怎么跑的,随便删一个变量就直接报错。

我们以App.xmal和App.xaml.cs为例
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

如何确定启动页面

在这里插入图片描述

xmal文件如何引用别的文件

在这里插入图片描述

如何引用

在这里插入图片描述
在这里插入图片描述

WPF是如何创建元素,改变元素的

WPF进行了高度的页面和业务分割,然后通过编译,将对应的页面和文件进行映射。所有我们所有的元素创建和简单的交互事件都在xmal进行。

WPF的元素创建和简单属性赋值

以一个简单的按钮为例

在布局元素中创建控件。

<Grid><Button  Content="Show Msg!"//显示的文字Click="Button_Click"//点击事件Width="100"//宽度Height="30" />//高度
</Grid>

被<>符合包裹住的是标签,<>后续跟着的就是属性。在上面的例子中,Button是标签,Grid也是标签。Content、Click、Width、Height都是属性。
实现效果

在这里插入图片描述

WPF的树形界面

WPF的xmal和html很像,都是标记性语言

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这个树形层级结构就是WPF的层级。

如果想具体了解,可以去看我之前写的文章。
WPF 如何实时查看页面元素如何使用实时可视化树

Xmal属性赋值

Xmal一共有三种属性赋值的方式。

  • 行内标签:默认的赋值方式
  • 属性标签:字符串输入转换数据类型
  • 扩展标签

为什么要多种属性赋值

我们看一个最简单的Button按钮

<Grid><Button  Content="Show Msg!"//字符串标签Click="Button_Click"Width="100"//属性标签Height="30" />
</Grid>

我们可以看到,我们赋值的值都是字符串。像Content就肯定是字符串,但是Width和Height,属性值应该是数字,但是我们输入的也是字符串。那就说明一点:我们可以对复制的字符串进行转换。

属性转换

属性转换的目的是为了我们通过标签属性去生成一些复杂的信息。比如Height = “100”。Height赋值一个字符串,里面肯定转换成了一个数字。

我们新建一个Person类

MainWindow.cs

namespace WpfLearnTest
{public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void Button_Click(object sender, RoutedEventArgs e)//按钮事件{///找到资源字典中名字为person的类Person _model = (Person)this.FindResource("person");MessageBox.Show(_model.Name);}}public class Person{public string Name { get; set; }public Person Chil { get; set; }}
}

MainWindow.xmal

<Window x:Class="WpfLearnTest.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:WpfLearnTest"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.Resources><local:Person x:Key="person" Name="小王" />//声明Person类</Window.Resources><Grid><Button  Content="Show Msg!"Click="Button_Click"//添加点击按钮Width="100"Height="30" /></Grid>
</Window>

实现结果

在这里插入图片描述
成功的原因是因为我们的Person类的Name是字符串,但是如果不是字符串会如何?
在这里插入图片描述

在这里插入图片描述

我们可以的看到Child报错。字符串不能直接转Person类。

解决方法
	///引入属性转换[TypeConverterAttribute(typeof(NameToPersonTypeConverter))]public class Person{public string Name { get; set; }public Person Child { get; set; }}/// <summary>/// 添加属性转换/// </summary>public class NameToPersonTypeConverter : TypeConverter{public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value){string name = value.ToString();Person child = new Person();child.Name = name;return child;}}

使用效果:

在这里插入图片描述
在这里插入图片描述
运行结果成功!

在这里插入图片描述

属性标签

需要解决的问题。

在这里插入图片描述

在网页端,Html+css中是如何实现的?

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>一个简单的网页</title></head><body><div><button style="width: 100px;height: 30px;"><div style="height: 10px;min-width: 10px;border: 1px solid red;display: inline-block;"></div></button></div></body>
</html>

在这里插入图片描述
在xmal中也可以使用嵌套

<Window x:Class="WpfLearnTest.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:WpfLearnTest"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Grid><Button Width="100"Height="30"><Rectangle Width="20"Height="20"Stroke="DarkGreen"Fill="LawnGreen" /></Button></Grid>
</Window>

在这里插入图片描述
但是xmal支持我们使用属性标签 的方式填写

        <Button Click="Button_Click"Width="100"Height="30"><Button.Content>//属性标签,对应button的content值<Rectangle Width="20"Height="20"Stroke="DarkGreen"Fill="LawnGreen" /></Button.Content></Button>

实现的效果是一样的
在这里插入图片描述

那嵌套一个属性标签到底有什么用呢?

结论是在这个案例里面没有区别。

在实时可视化树中也没区别
在这里插入图片描述

属性标签的特点和缺点

我们现在有一个需求
在这里插入图片描述

        <Rectangle Width="200"Height="160"Stroke="Blue"Fill="LightBlue" />

我们看看html+css是如何解决的
网页端用html+css+JS分离。只让html声明元素,让css修改样式。JS在使用中原则上不添加或者删除html元素(虽然可以进行DOM操作实现,但是这样会将提高耦合,容易形成屎山代码),而是通过css的display:none。来进行页面样式的显示或者不显示。

声明页面元素
修改Html样式
动态html对应的CSS
实现业务逻辑
原则上不能直接操控Html
的元素生成
原则上不能修改CSS的样式内容
用户页面
Html
CSS
JS
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>一个简单的网页</title>
</head>
<body><div id="box"></div>
</body>
</html>
<style type="text/css">#box {height: 200px;background-color: red;background-image: linear-gradient(to bottom right, red, blue);}
</style>

实现效果
在这里插入图片描述

属性标签的缺点

我们看看WPF实现上述效果要怎么写?

<Rectangle Width="200"Height="160"Stroke="Blue"><Rectangle.Fill><LinearGradientBrush><LinearGradientBrush.StartPoint><Point  X="0"Y="0" /></LinearGradientBrush.StartPoint><LinearGradientBrush.EndPoint><Point X="1"Y="1" /></LinearGradientBrush.EndPoint><LinearGradientBrush.GradientStops><GradientStop Offset="0.2"Color="LightBlue" /><GradientStop Offset="0.7"Color="DarkBlue" /><GradientStop Offset="1.0"Color="LightBlue" /></LinearGradientBrush.GradientStops></LinearGradientBrush></Rectangle.Fill></Rectangle>

在这里插入图片描述

我们可以看到只是个单纯的渐变效果,就写的特别麻烦

当然,我们可以使用行内标签来进行优化

<Rectangle Width="200"Height="160"Stroke="Blue"><Rectangle.Fill><LinearGradientBrush StartPoint="0,0" EndPoint="1,1">//使用行内标签来对代码进行优化<LinearGradientBrush.GradientStops><GradientStop Offset="0.2"Color="LightBlue" /><GradientStop Offset="0.7"Color="DarkBlue" /><GradientStop Offset="1.0"Color="LightBlue" /></LinearGradientBrush.GradientStops></LinearGradientBrush></Rectangle.Fill></Rectangle>

我们可以使用资源字典来优化

 <Window.Resources><Style x:Key="MyButton"TargetType="Button"><Style.Setters><Setter Property="Content"Value="" /></Style.Setters></Style><Style x:Key="MyRectFill" TargetType="Rectangle"><Style.Setters><Setter Property="Fill" ><Setter.Value><LinearGradientBrush StartPoint="0,0"EndPoint="1,1"><GradientStop Offset="0.2"Color="LightBlue" /><GradientStop Offset="0.7"Color="DarkBlue" /><GradientStop Offset="1.0"Color="LightBlue" /></LinearGradientBrush></Setter.Value></Setter></Style.Setters></Style></Window.Resources><Grid><Rectangle Width="200"Height="160"Stroke="Blue" Style="{StaticResource MyRectFill}" ></Rectangle></Grid>

我们保证了页面元素的简洁化,但是由于WPF运行的关系,Window.Resources只能放在页面元素之前。而且由于C#和Xmal是强定义语言,所以写起来一定要对元素内容进行声明。

CSS里面5行能解决的事情,在Xmal里面有10行才能解决。

扩展标签

我们刚刚写的代码中

        <Rectangle Width="200"Height="160"Stroke="Blue" Style="{StaticResource MyRectFill}" >//这个就是扩展标签</Rectangle>

扩展标签使用{}的形式,将属性值包含在里面。这时候我们输入的就不是字符串,而是一个属性对象。如果同学们学过Vue 就能了解到这个类似于Vue 的差值表达式{{value}}。

标签扩展一般和属性绑定配合,我过会会讲解如何使用属性绑定。这个是WPF的重点。

WPF的属性绑定

页面元素相互赋值

我之前说过WPF中的内容关系如下

负责所有的页面元素
样式和简单的用户交互
C#
复杂的交互逻辑
业务逻辑
Xmal
负责Style管理和资源管理
windows.Resource
Style
负责样式管理,触发器管理
xmal元素
负责声明元素
用户页面
数据交互和触发事件回调

而xmal里面,元素的是可以沟通的,在Web端则不行。Web需要通过JS事件触发来修改数据。这个就是事件驱动型。事件驱动型认为所有的页面交互都是由事件触发的,两个页面元素的沟通必须要有一个中间事件。

修改对应元素值
页面A数据修改
触发JS函数
B元素修改

Xmal中,则是数据驱动型,或者可以看做匿名事件。就是我没必要声明一个事件,我直接将值给他就行了

A被修改属性
xmal元素A
xmal元素B联动

xmal代码

    <Grid><Grid.RowDefinitions><RowDefinition Height="24" /><RowDefinition Height="4" /><RowDefinition Height="24" /></Grid.RowDefinitions><TextBox  x:Name="tb"Text="{Binding ElementName=sld,Path=Value}" /><Slider  x:Name="sld"Grid.Row="2"Value="50"Maximum="100"Minimum="0" /></Grid>

在这里插入图片描述

WPF 数据绑定会在后面的Prism框架中进行详细说明。

WPF组件化

组件化,即将一个会重复复用界面封装成一个组件。WPF一共有一下4个类

在这里插入图片描述

  • 窗口:一个窗口。窗口之间不能嵌套
  • 页:很少用,也不知道干什么的,好像是网页的。
  • 用户控件:套在窗口上面的。用于抽象化组件
  • 资源字典:用于管理WPF资源的,比如样式,控件。

我们新建一个WPF资源类

在这里插入图片描述
在这里插入图片描述
新建项目

然后添加如下代码

UserControl1.xmal

<UserControl x:Class="ControlLibrary.UserControl1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:local="clr-namespace:ControlLibrary"mc:Ignorable="d"d:DesignHeight="160"d:DesignWidth="240"Background="LightBlue"><Canvas><TextBox Canvas.Left="110"TextWrapping="Wrap"x:Name="textBox1"Canvas.Top="10"Width="120"HorizontalAlignment="Left"VerticalAlignment="Center"/><TextBox Canvas.Left="110"TextWrapping="Wrap"x:Name="textBox3"Canvas.Top="105"Width="120"HorizontalAlignment="Left"VerticalAlignment="Top" /><TextBox Canvas.Left="110"TextWrapping="Wrap"x:Name="textBox2"Canvas.Top="63"Width="120"HorizontalAlignment="Left"VerticalAlignment="Center" /><TextBlock TextWrapping="Wrap"Canvas.Top="10"Canvas.Left="10"><Run Language="zh-cn"Text="num1" /></TextBlock><TextBlock TextWrapping="Wrap"Canvas.Top="63"Canvas.Left="10"HorizontalAlignment="Center"VerticalAlignment="Top"><Run Text="num" /><Run Language="zh-cn"Text="2" /></TextBlock><TextBlock TextWrapping="Wrap"Canvas.Top="107"Canvas.Left="10"HorizontalAlignment="Center"VerticalAlignment="Top"><Run Language="zh-cn"Text="总计" /></TextBlock><Button Content="计算"Canvas.Left="126"Canvas.Top="136"HorizontalAlignment="Left"VerticalAlignment="Center"Width="88"Click="Button_Click" /></Canvas>
</UserControl>

UserControl.xmal.cs

using System;
......namespace ControlLibrary
{/// <summary>/// UserControl1.xaml 的交互逻辑/// </summary>public partial class UserControl1 : UserControl{public UserControl1(){InitializeComponent();}private void Button_Click(object sender, RoutedEventArgs e){this.textBox3.Text = ( int.Parse(this.textBox1.Text) + int.Parse(this.textBox2.Text) ).ToString();}}
}

在这里插入图片描述

然后添加对其的引用

在这里插入图片描述
每个项目都重新生成一下
在这里插入图片描述

在主函数中引用

<Window x:Class="WpfLearnTest.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:WpfLearnTest"xmlns:sys="clr-namespace:System.Security.Claims;assembly=mscorlib"xmlns:controls="clr-namespace:ControlLibrary;assembly=ControlLibrary"mc:Ignorable="d"Title="MainWindow"Height="450"Width="800"><Grid><Grid.RowDefinitions><RowDefinition /><RowDefinition /></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><controls:UserControl1 Grid.Row="0"Grid.Column="0" /><controls:UserControl1 Grid.Row="1"Grid.Column="1" /><controls:UserControl1 Grid.Row="1"Grid.Column="0" /><controls:UserControl1 Grid.Row="0"Grid.Column="1" /></Grid>
</Window>

在这里插入图片描述

使用结果
在这里插入图片描述

可以直接引入,而且能够执行用户控件的代码(总计的结果为num1+num2)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/1352.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Layui实现管理页面

基于Layui实现的后台管理页面&#xff08;仅前端&#xff09; 注&#xff1a;这是博主在帮朋友实现的一个简单的系统前端框架&#xff08;无后端&#xff09;&#xff0c;跟大家分享出来&#xff0c;可以直接将对应菜单跟html文件链接起来&#xff0c;页面使用标签页方式存在&…

如何在Maven中发布项目到Nexus私有服务器

本篇环境 nexus-3.55.0-01&#xff0c; Nexus安装在本地服务器 http://localhost:8081/maven-3.9.2 发布步骤 在项目机器的Maven的 settings.xml 配置Nexus的账号/密码 在settings.xml 的 <servers>节点增加 <server> 节点&#xff0c; 配置 Nexus 的登陆账号和…

OPENCV 训练分类器一

第一步&#xff0c;安装OPENCV 见最新openCV-Python安装教程(opencv-python版本4.4.0, Python版本: 3.9)_python安装opencv_这个人不是画家的博客-CSDN博客 第二步&#xff0c;下面是修正过后的Python 将文件夹下面所有的图片转换成灰色小图像&#xff0c;用于存正片用的。…

NXP i.MX 8M Plus工业开发板硬件说明书--下册( 四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)

前 言 本文档主要介绍创龙科技TLIMX8MP-EVM评估板硬件接口资源以及设计注意事项等内容。 创龙科技TLIMX8MP-EVM是一款基于NXP i.MX 8M Plus的四核ARM Cortex-A53 单核ARM Cortex-M7异构多核处理器设计的高性能工业评估板&#xff0c;由核心板和评估底板组成。ARM Cortex-A5…

如何录音转文字?这份录音转文字教程你必须知道

在现代快节奏的工作环境中&#xff0c;电脑会议录音转文字成为了一项非常重要的任务。但是很多人不知道电脑会议录音转文字怎么转&#xff1f;如果你也正有这样的疑问&#xff0c;那么你就来对地方了&#xff01;在本篇文章中&#xff0c;我们将为你介绍几款备受推崇的录音转文…

撸一遍STM32最小系统板

采样的MCU型号为STM32F405RGT6&#xff0c;目前这款芯片价格便宜性能好。 1 电机控制会用到单片机的哪些功能&#xff1f; GPIO&#xff08;通用输入/输出&#xff09;&#xff1a;单片机的GPIO引脚可以用于控制电机的开关、使能以及接收传感器的反馈信号。通过设置GPIO引脚的…

【网页复习】4道大题

&#x1f38a;专栏【 前端易错合集】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 文章目录 &#x1f354;实现如图的导航栏⭐代码&#x1f384;注…

Java安全——安全管理器

Java安全 安全管理器 Java安全管理器是一个Java安全模型中的一个组件&#xff0c;主要的作用是提高Java应用程序的安全性。Java应用程序中的每个线程都会对安全管理器进行检查&#xff0c;在执行代码之前&#xff0c;会先经过安全管理器的核验&#xff0c;安全管理器根据代码来…

445端口是啥?445端口怎么关闭?

445端口是Windows系统中的SMB协议&#xff0c;用于文件共享和网络打印功能。然而&#xff0c;这个端口也是黑客攻击的重要入口之一。那么&#xff0c;如何关闭445端口&#xff0c;保护自己的计算机安全呢&#xff1f; 关闭445端口的方法 1.在“控制面板”中打开“管理员工具”…

Unity 中的旋转、targetFrameRate、 vSyncCount、Time

1. 旋转&#xff1a; Unity 中的旋转用eulerAngle 表示&#xff0c;但在内部是以quaternion存储。欧拉角旋转围绕三个轴进行三次独立旋转&#xff0c;依次是z、x、y。To convert from Euler angles to quaternions, you can use the Quaternion.Euler function.To convert a q…

android 如何分析应用的内存(九)——libc回调

android 如何分析应用的内存&#xff08;九&#xff09; 接上文&#xff0c;在前面文章中&#xff0c;介绍了bionic库提供的各种功能&#xff0c;其中包括&#xff1a; 自定义的mallocmalloc hookmalloc debug 接下来&#xff0c;介绍的是bionic库提供的libc回调功能&#x…

Docker学习笔记7

启动一个运行httpd服务的容器&#xff1a; docker run -it --namec3 centos:latest /bin/bash 在容器中安装apache服务&#xff1a; yum install -y httpd 在这个过程中遇到一个问题&#xff1a; Error: Failed to download metadata for repo appstream: Cannot prepare …