WPF控件模板2

news/2024/11/28 7:33:20/

在控件模板和为其提供支持的代码之间有一个隐含约定。如果使用自定义控件模板替代控件的标准模板,就需要确保新模板能够满足控件的实现代码的所有需要。

在简单控件中,这个过程就比较容易,因为对模板几乎没有(或者完全没有)什么真正的要求。对于复杂控件,问题就显得有些微妙了,因为控件的外观和实现不可能是完全相互独立的。对于这种情况,控件需要对其可视化显示做出一些假设,而不管曾经被设计得多么好。

在前面已经看到了控件模板的这种需求的两个例子,占位元素(如ContentPresenter和ItemsPresenter)和模板绑定。为成功地创建控件模板,需要仔细查看相关控件的标准模板,并注意分析这些技术的用法,然后将它们应用到自己的模板中。

嵌套的模板

按钮控件的模板可分解成几个较简单的部分。然而,许多模板并非如此简单。在某些情况下,控件模板将包含每个自定义模板也需要的大量元素。而在有些情况下,改变控件的外观涉及创建多个模板。

例如,假设计划修改熟悉的ListBox控件。创建这个示例的第一部是为ListBox控件设计模板,并酌情添加自动应用模板的样式。

    <Style TargetType="{x:Type ListBox}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBox}"><Border Name="Border" Background="{StaticResource ListBoxBackgroundBrush}" BorderBrush="{StaticResource StandardBorderBrush}" BorderThickness="1" CornerRadius="3"><ScrollViewer Focusable="False"><ItemsPresenter Margin="2"></ItemsPresenter></ScrollViewer></Border></ControlTemplate></Setter.Value></Setter></Style>

该样式使用两个画刷绘制边框和背景。实际模板是标准模板ListBox的简化版本。在Border元素内部是为列表提供滚动功能的 ScrollViewer 元素以及容纳所有列表项的 ItemsPresenter 元素。

对于该模板,最值得注意之处是它未提供的功能——配置列表中各项的外观。没有改功能,被选择的元素总是使用熟悉的蓝色背景突出显示。为改变这种行为,需要为ListBoxItem控件添加控件模板,ListBoxItem 控件时封装列表中每个单独元素内容的内容控件。

与ListBox模板一样,可使用元素类型样式应用ListBoxItem模板。下面的基本模板在一个不可见的边框中封装了每个项。因为ListBoxItem是内容控件,所以需要使用ContentPresenter 元素在其内部放置项的内容。除这些基本内容外,还有当鼠标移动到项上或单击时做出响应的触发器:

    <Style TargetType="{x:Type ListBoxItem}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBoxItem}"><Border Name="Border" BorderThickness="2" CornerRadius="3" Padding="1" SnapsToDevicePixels="True"><ContentPresenter /></Border><ControlTemplate.Triggers><EventTrigger RoutedEvent="ListBoxItem.MouseEnter"><EventTrigger.Actions><BeginStoryboard><Storyboard><DoubleAnimation Storyboard.TargetProperty="FontSize" To="20" Duration="0:0:1"></DoubleAnimation></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger><EventTrigger RoutedEvent="ListBoxItem.MouseLeave"><EventTrigger.Actions><BeginStoryboard><Storyboard><DoubleAnimation Storyboard.TargetProperty="FontSize" BeginTime="0:0:0.5" Duration="0:0:0.2"></DoubleAnimation></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger><Trigger Property="IsMouseOver" Value="True"><Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource HoverBorderBrush}"/></Trigger><Trigger Property="IsSelected" Value="True"><Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/><Setter TargetName="Border" Property="TextBlock.Foreground" Value="{StaticResource SelectedForegroundBrush}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>

总之,可以使用这两个模板创建当鼠标移动到当前定位的项上时使用动画放大项的列表框。因为每个ListBoxItem可具有自己的动画,所以当用户在列表框中上下移动鼠标时,将看到几个项开始增大,然后再次收缩。需要注意,缩小动画省略了From和To属性,通过这种方式,缩小动画总将文本从当前尺寸缩小到它原来的尺寸。

修改滚动条

列表框还有一个方面没有改变:右边的滚动条。它是ScrollViewer 元素的一部分,ScrollViewer元素是ListBox模板的一部分。尽管这里重新定义了ListBox模板,但没有替换ScrollBar的ScrollViewer。

为自定义该细节,可为ListBox控件创建一个新的ScrollViewer模板,然后可将 ScrollViewer模板指向自定义的ScrollBar模板。然而 ,还有更简单的选择。可创建一个改变所有ScrollBar控件模板的特性于元素类型的样式。这样就避免了创建ScrollViewer模板所需的额外工作。

当然,还需要考虑这种设计会对应用程序的其他部分造成什么影响。如果创建元素类型样式ScrollBar,并将其添加到窗口的Resources集合中,对于窗口的所有控件,无论何时使用ScrollBar控件,都会具有新样式的滚动条,这可能正是您所希望的效果。另一方面,如果希望只改变ListBox控件中的滚动条,就必须为ListBox控件本身的资源集合添加元素类型样式 ScrollBar。最后,如果希望改变整个应用程序中所有滚动条的外观,可将该样式添加到 App.xaml文件的资源集合中。

ScrollBar控件出奇复杂,它实际上是一个由更小部分组成的集合。

滚动条的背景有Track类表示——实际上是一个具有阴影并且被拉伸沾满整个滚动条长度的矩形。滚动条的末尾处是按钮,通过这些按钮可以向上或向下(或向左或向右)滚动一个步长。这些按钮时RepeatButton类的实例,该类继承自ButtonBase类。RepeatButton类和普通Button类之间的重要区别在于,如果在RepeatButton按钮上保持鼠标为按下状态,就会反复触发Click事件(对于滚动条这是非常方便的)。

在滚动条的中间是代表当前滚动内容中当前位置的Thumb元素。并且最有趣的是,滑块两侧的空白实际上由另外两个RepeatButton 对象构成,它们是透明的。当单击这两个按钮中的一个时,滚动条会滚动一整页(一页是滚动内容所在的可见窗口中的内容量)。通过单击滑块两侧的条形区域,可快速浏览滚动内容,这一功能是大家所熟悉的。

下面是用于垂直滚动条的模板:

    <ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}"><Grid><Grid.RowDefinitions><RowDefinition MaxHeight="18"/><RowDefinition Height="*"/><RowDefinition MaxHeight="18"/></Grid.RowDefinitions><RepeatButton Grid.Row="0" Height="18" Style="{StaticResource ScrollBarLineButtonStyle}" Command="ScrollBar.LineUpCommand" ><Path Fill="{StaticResource GlyphBrush}" Data="M 0 4 L 8 4 L 4 0 Z"></Path></RepeatButton><Track Name="PART_Track" Grid.Row="1" IsDirectionReversed="True" ViewportSize="0"><Track.DecreaseRepeatButton><RepeatButton Command="ScrollBar.PageUpCommand" Style="{StaticResource ScrollBarPageButtonStyle}"></RepeatButton></Track.DecreaseRepeatButton><Track.Thumb><Thumb Style="{StaticResource ScrollBarThumbStyle}"></Thumb></Track.Thumb><Track.IncreaseRepeatButton><RepeatButton Command="ScrollBar.PageDownCommand" Style="{StaticResource ScrollBarPageButtonStyle}"></RepeatButton></Track.IncreaseRepeatButton></Track><RepeatButton Grid.Row="3" Height="18" Style="{StaticResource ScrollBarLineButtonStyle}" Command="ScrollBar.LineDownCommand"><Path Fill="{StaticResource GlyphBrush}" Data="M 0 0 L 4 4 L 8 0 Z"></Path></RepeatButton></Grid></ControlTemplate>

一旦理解滚动条的多部分结构,上面的模板就非常直观了。下面列出需要注意的几个要点:

1、垂直滚动条由一个包含三行的网格构成。顶行和底行容纳两端的按钮(并显示为箭头)。它们固定占用18个单位。中间部分容纳Track元素,占用了剩余空间。

2、两端的RepeatButton元素使用相同的样式。唯一的区别是Content属性,该属性包含了一个用于绘制箭头的Path对象,因为顶部具有上箭头而底部的按钮具有下箭头。为简明起见,这些箭头使用微语言路径。其他细节(如背景填充和箭头周围显示的圆圈)是在控件模板中定义的。

3、两个按钮都链接到ScrollBar类的命令(LineUpCommand 和 LineDownCommand)。这正是其工作原理。只要提供链接到这个命令的按钮即可,不必考虑按钮的名称是什么,也不必考虑其外观像什么或使用哪个特定的类。

4、Track元素名为PART_Track。为使ScrollBar类能够成功的关联到它的代码,必须使用这个名称。如果查看ScrollBar类的默认模板(类似上面的模板,但更长一些),也会看到该元素。

5、Track.ViewportSize 属性被设置为0,。这是该模板特有的实现细节,可确保Thumb元素总有相同的尺寸(通常,滑块根据内容按比例地改变尺寸,因此如果滚动的内容在窗口中基本上能够显示,这是滑块会变得较长)。

6、Track元素封装了两个RepeatButton对象和Thumb元素。同样,这些按钮通过命令连接到适当的功能。

这里模板使用了键名,明确指定将它作为垂直滚动条,可确保它不能被自动应用,即使同时设置了TargetType属性。这里使用这种方法的原因是,该模板只适用于垂直方向的滚动条。而且,如果ScrollBar.Orientation属性设置为Vertical,元素类型样式会使用触发器自动应用控件模板:

    <Style TargetType="{x:Type ScrollBar}"><Setter Property="SnapsToDevicePixels" Value="True"/><Setter Property="OverridesDefaultStyle" Value="true"/><Style.Triggers><Trigger Property="Orientation" Value="Vertical"><Setter Property="Width" Value="18"/><Setter Property="Height" Value="Auto" /><Setter Property="Template" Value="{StaticResource VerticalScrollBar}" /></Trigger></Style.Triggers></Style>

尽管可以使用相同的基本部分很容易地创建水平滚动条,但这里没有采取该步骤,从而保留了正常样式的水平滚动条。

最后一项任务是填充格式化各个RepeatButton对象和Thumb元素的样式。这些样式比较简单,但它们确实改变了滚动条的标准外观。

    <Style x:Key="ScrollBarLineButtonStyle" TargetType="{x:Type RepeatButton}"><Setter Property="Focusable" Value="False"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type RepeatButton}"><Grid Margin="1"><Ellipse Name="Border" StrokeThickness="1" Stroke="{StaticResource StandardBorderBrush}" Fill="{StaticResource StandardBrush}"></Ellipse><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter></Grid><ControlTemplate.Triggers><Trigger Property="IsPressed" Value="true"><Setter TargetName="Border" Property="Fill" Value="{StaticResource PressedBrush}" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="ScrollBarPageButtonStyle" TargetType="{x:Type RepeatButton}"><Setter Property="IsTabStop" Value="False"/><Setter Property="Focusable" Value="False"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type RepeatButton}"><Border Background="Transparent" /></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="ScrollBarThumbStyle" TargetType="{x:Type Thumb}"><Setter Property="IsTabStop" Value="False"/><Setter Property="Focusable" Value="False"/><Setter Property="Margin" Value="1,0,1,0" /><Setter Property="Background" Value="{StaticResource StandardBrush}" /><Setter Property="BorderBrush" Value="{StaticResource StandardBorderBrush}" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Thumb}"><Ellipse Stroke="{StaticResource StandardBorderBrush}" Fill="{StaticResource StandardBrush}"></Ellipse></ControlTemplate></Setter.Value></Setter></Style>

与正常滚动条不同,在该模板中没有为Track元素指定背景,所以保持原来的透明背景。这样,列表框的轻微阴影渐变可透过滚动条显示。

至此,ListBox自定义模板就完成了,这里定义的ScrollBar样式会自动应用于ListBox模板中的ScrollViewer上。

代码清单:

Resources/Brush.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><SolidColorBrush x:Key="StandardBorderBrush" Color="#888" /><SolidColorBrush x:Key="StandardBackgroundBrush" Color="#FFF" /><SolidColorBrush x:Key="HoverBorderBrush" Color="#DDD" /><SolidColorBrush x:Key="SelectedBackgroundBrush" Color="Gray" /><SolidColorBrush x:Key="SelectedForegroundBrush" Color="White" /><LinearGradientBrush x:Key="ListBoxBackgroundBrush" StartPoint="0,0" EndPoint="1,0.001"><GradientBrush.GradientStops><GradientStopCollection><GradientStop Color="White" Offset="0.0" /><GradientStop Color="White" Offset="0.6" /><GradientStop Color="#DDDDDD" Offset="1.2"/></GradientStopCollection></GradientBrush.GradientStops></LinearGradientBrush><LinearGradientBrush x:Key="StandardBrush" StartPoint="0,0" EndPoint="0,1"><GradientBrush.GradientStops><GradientStopCollection><GradientStop Color="#FFF" Offset="0.0"/><GradientStop Color="#CCC" Offset="1.0"/></GradientStopCollection></GradientBrush.GradientStops></LinearGradientBrush><SolidColorBrush x:Key="GlyphBrush" Color="#444" /><LinearGradientBrush x:Key="PressedBrush" StartPoint="0,0" EndPoint="0,1"><GradientBrush.GradientStops><GradientStopCollection><GradientStop Color="#BBB" Offset="0.0"/><GradientStop Color="#EEE" Offset="0.1"/><GradientStop Color="#EEE" Offset="0.9"/><GradientStop Color="#FFF" Offset="1.0"/></GradientStopCollection></GradientBrush.GradientStops></LinearGradientBrush>
</ResourceDictionary>

Resources/ScrollBar.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Brush.xaml"></ResourceDictionary></ResourceDictionary.MergedDictionaries><Style x:Key="ScrollBarLineButtonStyle" TargetType="{x:Type RepeatButton}"><Setter Property="Focusable" Value="False"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type RepeatButton}"><Grid Margin="1"><Ellipse Name="Border" StrokeThickness="1" Stroke="{StaticResource StandardBorderBrush}" Fill="{StaticResource StandardBrush}"></Ellipse><ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter></Grid><ControlTemplate.Triggers><Trigger Property="IsPressed" Value="true"><Setter TargetName="Border" Property="Fill" Value="{StaticResource PressedBrush}" /></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="ScrollBarPageButtonStyle" TargetType="{x:Type RepeatButton}"><Setter Property="IsTabStop" Value="False"/><Setter Property="Focusable" Value="False"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type RepeatButton}"><Border Background="Transparent" /></ControlTemplate></Setter.Value></Setter></Style><Style x:Key="ScrollBarThumbStyle" TargetType="{x:Type Thumb}"><Setter Property="IsTabStop" Value="False"/><Setter Property="Focusable" Value="False"/><Setter Property="Margin" Value="1,0,1,0" /><Setter Property="Background" Value="{StaticResource StandardBrush}" /><Setter Property="BorderBrush" Value="{StaticResource StandardBorderBrush}" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Thumb}"><Ellipse Stroke="{StaticResource StandardBorderBrush}" Fill="{StaticResource StandardBrush}"></Ellipse></ControlTemplate></Setter.Value></Setter></Style><ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}"><Grid><Grid.RowDefinitions><RowDefinition MaxHeight="18"/><RowDefinition Height="*"/><RowDefinition MaxHeight="18"/></Grid.RowDefinitions><RepeatButton Grid.Row="0" Height="18" Style="{StaticResource ScrollBarLineButtonStyle}" Command="ScrollBar.LineUpCommand" ><Path Fill="{StaticResource GlyphBrush}" Data="M 0 4 L 8 4 L 4 0 Z"></Path></RepeatButton><Track Name="PART_Track" Grid.Row="1" IsDirectionReversed="True" ViewportSize="0"><Track.DecreaseRepeatButton><RepeatButton Command="ScrollBar.PageUpCommand" Style="{StaticResource ScrollBarPageButtonStyle}"></RepeatButton></Track.DecreaseRepeatButton><Track.Thumb><Thumb Style="{StaticResource ScrollBarThumbStyle}"></Thumb></Track.Thumb><Track.IncreaseRepeatButton><RepeatButton Command="ScrollBar.PageDownCommand" Style="{StaticResource ScrollBarPageButtonStyle}"></RepeatButton></Track.IncreaseRepeatButton></Track><RepeatButton Grid.Row="3" Height="18" Style="{StaticResource ScrollBarLineButtonStyle}" Command="ScrollBar.LineDownCommand"><Path Fill="{StaticResource GlyphBrush}" Data="M 0 0 L 4 4 L 8 0 Z"></Path></RepeatButton></Grid></ControlTemplate><Style TargetType="{x:Type ScrollBar}"><Setter Property="SnapsToDevicePixels" Value="True"/><Setter Property="OverridesDefaultStyle" Value="true"/><Style.Triggers><Trigger Property="Orientation" Value="Vertical"><Setter Property="Width" Value="18"/><Setter Property="Height" Value="Auto" /><Setter Property="Template" Value="{StaticResource VerticalScrollBar}" /></Trigger></Style.Triggers></Style>
</ResourceDictionary>

Resources/ListBox.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Brush.xaml"></ResourceDictionary><ResourceDictionary Source="ScrollBar.xaml"></ResourceDictionary></ResourceDictionary.MergedDictionaries><Style TargetType="{x:Type ListBox}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBox}"><Border Name="Border" Background="{StaticResource ListBoxBackgroundBrush}" BorderBrush="{StaticResource StandardBorderBrush}" BorderThickness="1" CornerRadius="3"><ScrollViewer Focusable="False"><ItemsPresenter Margin="2"></ItemsPresenter></ScrollViewer></Border></ControlTemplate></Setter.Value></Setter></Style><Style TargetType="{x:Type ListBoxItem}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type ListBoxItem}"><Border Name="Border" BorderThickness="2" CornerRadius="3" Padding="1" SnapsToDevicePixels="True"><ContentPresenter /></Border><ControlTemplate.Triggers><EventTrigger RoutedEvent="ListBoxItem.MouseEnter"><EventTrigger.Actions><BeginStoryboard><Storyboard><DoubleAnimation Storyboard.TargetProperty="FontSize" To="20" Duration="0:0:1"></DoubleAnimation></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger><EventTrigger RoutedEvent="ListBoxItem.MouseLeave"><EventTrigger.Actions><BeginStoryboard><Storyboard><DoubleAnimation Storyboard.TargetProperty="FontSize" BeginTime="0:0:0.5" Duration="0:0:0.2"></DoubleAnimation></Storyboard></BeginStoryboard></EventTrigger.Actions></EventTrigger><Trigger Property="IsMouseOver" Value="True"><Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource HoverBorderBrush}"/></Trigger><Trigger Property="IsSelected" Value="True"><Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/><Setter TargetName="Border" Property="TextBlock.Foreground" Value="{StaticResource SelectedForegroundBrush}"/></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
</ResourceDictionary>

MainWindow.xaml

<Window x:Class="TestControlTemplate2.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:TestControlTemplate2"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source="Resources/ListBox.xaml"></ResourceDictionary></ResourceDictionary.MergedDictionaries></ResourceDictionary></Window.Resources><Grid><ListBox Margin="5" ScrollViewer.CanContentScroll="False"><ListBoxItem>One</ListBoxItem><ListBoxItem>Two</ListBoxItem><ListBoxItem>Three</ListBoxItem><ListBoxItem>Four</ListBoxItem><ListBoxItem>Five</ListBoxItem><ListBoxItem>Six</ListBoxItem><ListBoxItem>Seven</ListBoxItem><ListBoxItem>EightEight</ListBoxItem><ListBoxItem>NineNineNine</ListBoxItem><ListBoxItem>TenTenTenTen</ListBoxItem><ListBoxItem>ElevenElevenElevenEleven</ListBoxItem><ListBoxItem>TwelveTwelveTwelveTwelveTwelve</ListBoxItem></ListBox></Grid>
</Window>

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 TestControlTemplate2;public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();}
}

http://www.ppmy.cn/news/1121425.html

相关文章

【腾讯云 TDSQL-C Serverless 产品体验】| 实战分享

目录 一. &#x1f981; 产品引入二. &#x1f981; TDSQL-C数据库使用体验——实战案例2.1 实战案例介绍2.2 实操指导1. 购买TDSQL数据库2. [配置选择](https://buy.cloud.tencent.com/cynosdb#/)3. 配置TDSQL-C 集群4. 点击授权并创建5. 记住主机名和端口6. 登录TDSQL7. 链接…

ROS-读取/map话题转化为pgm文件(代码版map_server)

在ROS-Navigation中有map_server的工具可以把2D SLAM的地图保存为pgm格式&#xff0c;但map_server只是工具&#xff0c;没办法很个性化自由的处理&#xff0c;这里介绍下源代码的形式&#xff1a; map_server.cpp #include <ros/ros.h> #include <nav_msgs/Occupan…

上位机通过Modbus转Profinet网关与变频器Modbus通讯案例

上位机与变频器Modbus通讯是通过Modbus转Profinet网关来实现的。这个网关可以理解为一个通信翻译器&#xff0c;负责将上位机通过Modbus协议发送的数据转换为Profinet协议&#xff0c;再通过Profinet网络与变频器进行通信。 上位机通过Modbus转Profinet网关与变频器Modbus通讯…

超自动化的未来

如今&#xff0c;部分企业正尝试从小规模的自动化开始&#xff0c;将超级自动化用于营销分析和数据库维护等不同任务。企业应该对超自动化进行更深入的挖掘&#xff0c;如果人们能够更加仔细的观察总结企业的每个流程&#xff0c;那么就能发现更多可以从自动化技术中受益的领域…

向表中的指定列插入数据

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 练习:向test02表,所有列,插入数据 复习下前面的 mysql> #插入记录 mysql> insert into test02 values(1, 张三, 男, 100.5); Query OK, 1 ro…

【算法思想】排序

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

C语言中各种接口标准

1.POSIX&#xff08;Portable Operating System Interface&#xff0c;可移植操作系统接口&#xff09;&#xff1a;是一个定义了操作系统接口标准的家族。它旨在提供一致的API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;和环境&a…

ONT P2MP定义与实现

在现代通信领域&#xff0c;光纤技术已成为最主要的宽带接入手段。尤其是在GPON或EPON这样的点到多点&#xff08;P2MP&#xff09;光纤网络中&#xff0c;其主要组件——OLT和ONT在确保高速、稳定和高效的网络连接中起到了至关重要的作用。本文将深入探讨ONT P2MP的定义、特点…