WPF Prims框架详解

文章目录

  • 前言
  • Prism基本使用
    • Prism选择,DryIoc还是Unity
    • Prism基本框架搭建
    • Prism动态更新
      • View和ViewModel对应关系
      • 参数动态更新
      • 函数动态绑定
    • prism新建项目模板
    • region
      • 使用事例
      • 测试是否限制空间
    • 消息订阅
      • 如何使用消息订阅
      • 使用建议
    • 路由导航
    • 对话框/弹窗功能
      • 实现代码

前言

Prims框架是WPF的一个框架,特点是集成了我们平常常用的开发模式,封装了很多常用的功能。例如消息通知,路由导航,Model绑定。

Prism基本使用

资料来源

WPF-Prism8.0核心教程(公益)

Prism选择,DryIoc还是Unity

根据网上的说明,DryIoc是更加效率更高的,但是我看Nuget下载数量里面,Unity下载数量比DryIoc高得多。具体没怎么用过,那就按照推荐用DryIoc好了。

Unity和DryIoc之间性能比较在这里插入图片描述

Prism基本框架搭建

在这里插入图片描述
在App.xaml里面,修改

App.xaml.cs

    /// <summary>
    /// 继承prism的PrismApplication类
    /// </summary>
    public partial class App : PrismApplication
    {
        //设置启动页
        protected override Window CreateShell()
        {
            //启动页为MainWindow
            return Container.Resolve<MainWindow>();

        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            
        }
    }

App.xaml

<!--xmlns:prism,引入prism命名空间-->
<!--prism:PrismApplication,继承prism下的PrismApplication类-->
<!--去掉StartupUrl,保证只有一个启动页-->
<prism:PrismApplication x:Class="PrismTest.App"
                        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:local="clr-namespace:PrismTest"
                        xmlns:prism="http://prismlibrary.com/">
</prism:PrismApplication>

Prism动态更新

View和ViewModel对应关系

在这里插入图片描述
View和ViewModel可以自动绑定,命名要求为。

  • Model:NameViewModel
  • View:Name/NameView(两者都可以)
    在View中添加入如下代码
xmlns:prism引入命名空间
prism:ViewModel设置自动绑定
可以不加,默认进行了绑定。
<Window ...
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True">

也可以在App.xaml里面强行绑定

在原文件件中取消绑定

app.xaml

        /// <summary>
        /// 路由管理
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //通过RegisterForNavigation进行强行绑定,强行让ViewA和ViewAViewModel进行绑定
            containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();
            
        }

参数动态更新

	//继承BindableBase接口
    public class MyListBoxItem : BindableBase
    {
        private string text;
        public string Text
        {
            get { return text; }
            set {  SetProperty(ref text, value);}//此方法为Prism提供
        }
    }

可以输入propp加tab键,模板输入,提交写代码效率

在这里插入图片描述

函数动态绑定

函数动态绑定需要用到委托类型,如果委托不明白需要自己回去了解一下

viewModel


//声明委托
public DelegateCommand TestBtn { get; set; }
//构造函数
public MainWindowViewModel()
{
    //实例化委托
    TestBtn = new DelegateCommand(() =>
    {
        //执行内容
    });
}

view

使用Command引用委托,如果没有TestBtn委托也不报错
        <Button Content="测试方法"
                FontSize="100"
                Grid.Row="1"
                Command="{Binding TestBtn}"/>

prism新建项目模板

在扩展,管理扩展中安装
在这里插入图片描述
我们在新建程序的时候会有Prism模板框架

在这里插入图片描述

使用时会提示使用什么容器,这里推荐DryIoc容器

在这里插入图片描述

新建文件路径如下

在这里插入图片描述

region

Prism将界面继续划分,分为多个Region,在Region中添加元素。

在这里插入图片描述

和WPF用户组件的区别。

  • Region相当于划分了空区域,WPF是有内容的区域。
  • Region相当于WPF用户控件的上级,用于包含用户控件

使用事例

MainWindow.xaml

    <Grid>
        <!--声明Region,名称为ContentRegion,使用名称来进行注入-->
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        
    </Grid>

UserControl1.xaml,用于放置在Region上面的用户控件

    <Grid>
        <TextBlock  Text="我是用户控件" FontSize="100"/>
    </Grid>

MainWindowViewModel.xaml

        //注册regionManager控件
        private readonly IRegionManager _regionManager;

        public MainWindowViewModel(IRegionManager regionManager)
        {
            this._regionManager = regionManager;
			//ContentRegion是窗口已声明的Region,使用字符串进行弱绑定
            regionManager.RegisterViewWithRegion("ContentRegion",typeof(UserControl1));
        }

生成效果
在这里插入图片描述

测试是否限制空间

在这里插入图片描述

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <!--声明Region,名称为ContentRegion,使用名称来进行注入-->
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
        
    </Grid>

实现效果

在这里插入图片描述

消息订阅

消息订阅是先订阅再发布有效,如果是先发布再订阅则无效。

如何使用消息订阅

 public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
                //声明委托
        public DelegateCommand TestBtn { get; set; }
        public DelegateCommand SendCommand { get; set; }
        private readonly IEventAggregator _eventAggregator;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }
        //构造函数
        public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator)
        {

            //实例化委托
            //订阅
            TestBtn = new DelegateCommand(() =>
            {
                eventAggregator.GetEvent<MessageEvent>().Subscribe(OnMessageRecevied);
            });
			//发送
            SendCommand = new DelegateCommand(() =>
            {
            	//执行参数
                eventAggregator.GetEvent<MessageEvent>().Publish("Hello Event");
            });
            
            this._eventAggregator = eventAggregator;
        }


        public void OnMessageRecevied(string msg)
        {
            Title += msg + "\r\n";
        }


        

		//消息订阅类
        public class MessageEvent: PubSubEvent<string> {
        }
    }

注意
eventAggregator.GetEvent<MessageEvent>()。MessageEvent是我们自己定义的,相当于订阅的消息主题。

eventAggregator.GetEvent().

  • Subscribe(OnMessageRecevied);
    • OnMessageRecevied是处理函数
  • Publish(“Hello Event”)
    • "Hello Event"是入参,因为OnMessageRecevied(string msg)

取消订阅

eventAggregator.GetEvent<MessageEvent>().Unsubscribe(OnMessageRecevied);

使用建议

  • 注意,这个是全局使用的,所以一般用于页面通讯
    • 例如:AView。我就用AViewEvent。一个页面对应一个事件通知。
  • 由于带入的参数不一定,所以我们可以设置Dictionary为入参,通过key值过滤来设置对应的函数。通过NetJson来快速传参。

路由导航

路由导航和Region是搭配使用的,专门用于页面转化

  • 新建切换用的用户控件ViewA,ViewB,ViewC。ViewA,B,C内容有区分,这里省略
    在这里插入图片描述
  • 在App.xaml.cs中注册页面
        /// <summary>
        /// 路由管理
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //将ViewA,B,C添加到导航,这样才能进行路由管理
            containerRegistry.RegisterForNavigation<ViewA>("ViewA");
            containerRegistry.RegisterForNavigation<ViewB>();
            containerRegistry.RegisterForNavigation<ViewC>();
        }

  • 在MainView中添加委托事件
   <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <Button Content="ViewA"
                    Command="{Binding OpenACommand}" />
            <Button Content="ViewB"
                    Command="{Binding OpenBCommand}" />
            <Button Content="ViewC"
                    Command="{Binding OpenC_Command}" />
            <Button Content="上一页"
                    Command="{Binding GoBackCommand}" />
            <Button Content="下一页"
                    Command="{Binding GoForwordCommand}"/>
        </StackPanel>
        <!--这个Region是我们等会切换窗口信息的-->
        <ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
    </Grid>

在MainiView里面管理导航


namespace PrismNavigation.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        /// <summary>
        /// 导航日志
        /// </summary>
        private IRegionNavigationJournal _journal;
        //Region,用于页面切换
        private readonly IRegionManager _regionManager;
        public DelegateCommand OpenACommand { get; set; }
        public DelegateCommand OpenBCommand { get; set; }
        public DelegateCommand OpenC_Command { get; set; }
        public DelegateCommand GoBackCommand { get; set; }
        public DelegateCommand GoForwordCommand { get; set; }


        public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator)
        {
            _regionManager = regionManager;
            OpenACommand = new DelegateCommand(OpenA);
            OpenBCommand = new DelegateCommand(OpenB);
            OpenC_Command = new DelegateCommand(OpenC);
            GoBackCommand = new DelegateCommand(GoBack);
            GoForwordCommand = new DelegateCommand(GoForword);

        }

        private void OpenA()
        {
            NavigationParameters para = new NavigationParameters
            {
                { "Value", "Hello Prism" }
            };
            //进行路由传参,ContentRegion是xmal中的Region名称,ViewA是在App.xmal中注册的名称,arg是日志回调,para是路由传递的参数
            _regionManager.RequestNavigate("ContentRegion", "ViewA", arg =>
            {
                ///获取导航日志
                _journal = arg.Context.NavigationService.Journal;
            }, para);

        }
        private void OpenB()
        {
            _regionManager.RequestNavigate("ContentRegion", "ViewB", arg =>
            {
                ///获取导航日志
                _journal = arg.Context.NavigationService.Journal;
            });

        }
        private void OpenC()
        {
            _regionManager.RequestNavigate("ContentRegion", "ViewC", arg =>
            {
                ///获取导航日志
                _journal = arg.Context.NavigationService.Journal;
            });

        }

        private void GoForword()
        {
            _journal.GoForward();
        }

        private void GoBack()
        {
            _journal.GoBack();
        }
    }
}

在ViewA中进行路由拦截

 public class ViewAViewModel :BindableBase, IConfirmNavigationRequest
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { SetProperty(ref _name, value); }
        }


        /// <summary>
        /// IConfirmNavigationRequest的路由离开拦截,
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <param name="continuationCallback"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
        {
            var res = true;
            if(MessageBox.Show("确认导航?","温馨提示",MessageBoxButton.YesNo) == MessageBoxResult.No)
            {
                res = false;
            }
            //如果res为true则拦截,true则放行
            continuationCallback?.Invoke(res);
        }

        /// <summary>
        /// 用于判断是否要重新创建新的事例,即是否保留之前的信息,True为重新创建。
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }
        /// <summary>
        /// 离开页面时触发,一般用于取消事件监听
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {

        }
        /// <summary>
        /// 显示页面前触发,一般用于设置事件监听
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            //拿到Key为Value的值,返回类型为string
            Name = navigationContext.Parameters.GetValue<string>("Value");
        }
    }

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

简单介绍

  • 路由导航是Region导航,必须要先将WPF用户控件添加到Region中才能进行导航
  • 在注册时,可以添加别名
    • containerRegistry.RegisterForNavigation<ViewA>(“别名”);
_regionManager.RequestNavigate("ContentRegion", "别名");//原本是ViewA的,可以替换成别名

对话框/弹窗功能

Prism将对话框这个常用的功能进行了封装。虽然叫对话框,但其实是弹窗的功能效果。

实现代码

app.xaml中

        /// <summary>
        /// 路由管理
        /// </summary>
        /// <param name="containerRegistry"></param>
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
			.......
            //这里也能起别名
            containerRegistry.RegisterDialog<MsgView,MsgViewModel>("别名");   
        }

MainViewModel使用这个弹窗

public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        /// <summary>
        /// 导航日志
        /// </summary>
        private IRegionNavigationJournal _journal;
        private readonly IRegionManager _regionManager;
        //注册弹窗服务
        private IDialogService _dialogService;
        public DelegateCommand OpenACommand { get; set; }

		//构造函数中传入对话框
        public MainWindowViewModel(IRegionManager regionManager,IEventAggregator eventAggregator,IDialogService dialogService)
        {
            _regionManager = regionManager;
            OpenACommand = new DelegateCommand(OpenA);
            GoForwordCommand = new DelegateCommand(GoForword);
            //使用对话框
            _dialogService = dialogService;

        }

        private void OpenA()
        {
        	//对话框传递的参数
            DialogParameters param = new DialogParameters();
            param.Add("Value", "paramTest");
            //打开名为MsgView的弹窗,并传递参数
            _dialogService.Show("MsgView", param, arg =>
            {
            	//弹窗关闭的回调函数,会有参数返回
                if(arg.Result == ButtonResult.OK)
                {
                    Debug.WriteLine("调试成功");
                }
            });
        }
    }

MsgView


    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition />
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="1" Text="{Binding Title}" FontSize="20"/>
        <Label Content="{Binding Title}"/>
        <DockPanel Grid.Row="2" LastChildFill="False">
            <Button Content="取消" Width="60"
                    DockPanel.Dock="Right"
                    Command="{Binding CancelCommand}" />
            <Button Content="确定"
                    Width="60"
                    DockPanel.Dock="Right"
                    Command="{Binding SaveCommand}"/>

        </DockPanel>
    </Grid>
public class MsgViewModel :BindableBase, IDialogAware
    {

        private string _title;
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        /// <summary>
        /// 用于弹窗关闭的回调函数
        /// </summary>
        public event Action<IDialogResult> RequestClose;

        public DelegateCommand SaveCommand { get; set; }

        public DelegateCommand CancelCommand { get; set; }

        public MsgViewModel() {
            SaveCommand = new DelegateCommand(() =>
            {
                DialogParameters keyValuePairs = new DialogParameters();
                keyValuePairs.Add("Value", Title);
                //执行弹窗关闭,并传入回调参数
                RequestClose?.Invoke(new DialogResult(ButtonResult.OK, keyValuePairs));
                
            });

            CancelCommand = new DelegateCommand(() =>
            {
                RequestClose?.Invoke(new DialogResult(ButtonResult.No));
            });
        }

        /// <summary>
        /// 能否打开窗口
        /// </summary>
        /// <returns></returns>
        public bool CanCloseDialog()
        {
            return true;
        }
        /// <summary>
        /// 关闭的方法
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        public void OnDialogClosed()
        {
            //throw new NotImplementedException();
        }
        /// <summary>
        /// 打开之前,接受弹窗传参
        /// </summary>
        /// <param name="parameters"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void OnDialogOpened(IDialogParameters parameters)
        {
            Title = parameters.GetValue<string>("Value");
        }
    }

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Element分页组件自定义样式

样式效果 页面代码 <el-paginationsize-change"handleSizeChange"current-change"handleCurrentChange":current-page"page.page":page-sizes"[10, 20, 30, 40]":page-size"page.size"layout"total, sizes, prev, …

HTML <map> 标签

实例 带有可点击区域的图像映射: <img src="planets.jpg" border="0" usemap="#planetmap" alt="Planets" /><map name="planetmap" id="planetmap"><area shape="circle" coords=&q…

Spring Boot 中的 @Field 注解详解

Spring Boot 中的 Field 注解详解 引言 Spring Boot 是目前 Java 生态圈中最受欢迎的 Web 应用开发框架之一&#xff0c;它提供了很多优秀的功能和工具&#xff0c;可以帮助开发者快速构建高效、可靠的 Web 应用程序。其中一个重要的功能就是数据绑定和验证&#xff0c;Sprin…

(阿里云)STM32L+BC20+MQTT协议传输温湿度,ADC,电压,GPS数据到阿里云物联网平台

1、材料准备 准备以下材料 2、设备连接 2.1 插入物联网卡 首先把BC20核心板从开发板上拆下来 然后将物联卡放置在BC20核心板内 物联卡放置完成将BC20核心板重新插入到开发板内&#xff08;注意不要弄错方向&#xff09; 同时接入天线 2.2 连接ST-Link仿真器 用3条杜邦线接…

DP485替代MAX485 RS485/RS422 收发器芯片

DP485E 是一款 5V 供电、半双工、低功耗、低摆率&#xff0c;完全满足 TIA/EIA-485 标准要求的 RS-485收发器。DP485E 工作电压范围为 4.75~5.25V&#xff0c;具备失效安全&#xff08;fail-safe&#xff09;、过温保护、限流保护、过压保护&#xff0c;控制端口热插拔输入等功…

飞行动力学 - 第10节-空间机动性、稳定性与操纵性概述 之 基础点摘要

飞行动力学 - 第10节-空间机动性、稳定性与操纵性概述 之 基础点摘要 1. 协调盘旋性能计算流程2. 一般盘旋2.1 动力学方程2.2 角点速度2.3 典型战斗机盘旋曲线 3. 空间机动能力4. 飞行动力学&#xff1a;飞行性能稳定性与操纵性5. 稳定性定义6. 飞行品质6.1 品质等级6.2 品质评…

从字节出来的测试总监,让我们用这份《测试用例规范》,再也没加班过。

经常看到无论是刚入职场的新人&#xff0c;还是工作了一段时间的老人&#xff0c;都会对编写测试用例感到困扰&#xff1f;例如&#xff1a; 固然&#xff0c;编写一份好的测试用例需要&#xff1a;充分的需求分析能力 理论及经验加持&#xff0c;作为测试职场摸爬打滚的老人&…

数据科学分析全流程步骤

知识图谱以结构化的“知识”来存储与表示海量数据&#xff0c;作为承载底层海量知识并支持上层智能应用的重要载体&#xff0c;它在智能时代中扮演了极其重要的角色。然而&#xff0c;由于知识图谱高度结构化的特点&#xff0c;我们常常需要构建结构化查询语句&#xff08;SPAR…

使用 jmeter 进行审批类接口并发测试

目录 前言&#xff1a; 背景&#xff1a; 难点&#xff1a; 场景 a&#xff1a; 场景 b&#xff1a; 前言&#xff1a; 使用JMeter进行审批类接口的并发测试是一种有效的方法&#xff0c;可以模拟多个用户同时对接口进行审批操作&#xff0c;以评估系统在高负载情况下的性…

LLM - DataCollatorForLanguageModeling 样本生成 by transformers

目录 一.引言 二.生成样本 By API 1.样本处理样式 2.DataCollatorForLanguageModeling 2.1 样本准备 2.2 API 生成 三.生成样本 By DIY 1.样本准备 2.data_colloator 实现 3.使用自定义 data_colloator 四.总结 一.引言 前面我们讲了 Baichuan7B 的 lora 微调步骤&a…

Qt添加第三方字体

最近开发项目时&#xff0c;据说不能用系统自带的微软雅黑字体&#xff0c;于是找一个开源的字体&#xff0c;思源黑体&#xff0c;这个是google和Adobe公司合力开发的可以免费使用。本篇记录一下Qt使用第三方字体的方式。字体从下载之家下载http://www.downza.cn/soft/266042.…

uniapp实现路由跳转拦截

场景&#xff1a;系统可以不登录就可以访问浏览商城&#xff0c;一些菜单&#xff08;购买、添加修改用户信息、添加地址、修改密码等&#xff09;需要进行登录才能操作。 思路&#xff1a; 1.新建公共js文件进行路由拦截&#xff0c;添加白名单。&#xff08;白名单菜单不需…

【压力传感器】LPS22DFTR、LPS33KTR 绝对 压力,ADP5131 排气式压力计 50kPa 6-DIP

LPS22DFTR MEMS纳米压力传感器是一款超紧凑型压阻式绝对压力传感器&#xff0c;可用作数字输出气压计。LPS22DF的功耗更低&#xff0c;与上一代产品相比压力噪声更低。该器件包括一个传感元件和一个IC接口&#xff0c;通过I2C、MIPI I3CSM或SPI接口从传感元件向应用程序进行通信…

【操作系统】几种基本页面置换算法的基本思想和流程图

目录 一、概述二、最佳置换算法&#xff08;OPT&#xff09;三、先进先出置换算法&#xff08;FIFO&#xff09;四、最近最久未使用置换算法&#xff08;LRU&#xff09;五、三种页面置换算法优缺点对比六、运行结果七、总结 一、概述 在地址映射过程中&#xff0c;若在页面中发…

在After Effects 加速渲染的 21个技巧,记得收藏!

如何减少After Effects 渲染时间&#xff1f; 1.升级内存 减少渲染时间的一种有效方法是升级 RAM&#xff08;随机存取存储器&#xff09;。RAM 在渲染过程中起着至关重要的作用&#xff0c;因为它存储并快速访问渲染任务所需的数据。增加系统中的 RAM 量可提供更多的数据存储…

Activity引擎(初次学习与总结梳理全记录,包括易混淆知识点分析,常用报错解决方案等)

最近工作需要使用Acticity框架处理审批业务&#xff0c;简单了解后能虽能很快的上手&#xff0c;但是对于Activity的整体认识并不够&#xff0c;特此花费很多精力全面的学习并记录。包含对很多的概念的第一次理解过程&#xff1b;对知识点的混淆地方的梳理&#xff1b;对实践过…

深度学习 / 数据处理:如何处理偏态数据

1 前言 当我们使用一个线性回归模型时&#xff0c;通常这个模型是在很大假设的前提下才有一个很好的结果&#xff1a; 1、假设预测因子和预测目标之间的关系是线性的2、数据不存在外在噪声&#xff1a;不存在一些极端的数据3、非共线性&#xff08; collinearity&#xff09;…

区块链生态发展

文章目录 前言以太坊的到来什么是图灵完备&#xff1f;什么是智能合约&#xff1f; 以太坊的应用去中心化应用 DApp代币发行 公有链&联盟链区块链应用总结 前言 前面的区块链文章有介绍区块链的诞生以及底层运行原理&#xff0c; 本文主要介绍一下区块链应用的发展&#x…

Windows Bat实现延时功能的几种常见方式

文章目录 1. 使用ping命令实现延时2. 使用timeout命令实现延时3. 使用choice命令实现延时4. 使用for循环实现延时5. 使用sleep命令实现延时6. 使用VBScript.sleep实现延时总结 在 bat批处理中实现延时功能的几种常用方式 1. 使用ping命令实现延时 使用ping命令可以实现延时的…

最小二乘拟合平面——拉格朗日乘子法

目录 一、算法原理二、代码实现1、python2、matlab 三、算法效果 一、算法原理 设拟合出的平面方程为&#xff1a; a x b y c z d 0 (1) axbyczd0\tag{1} axbyczd0(1) 约束条件为&#xff1a; a 2 b 2 c 2 1 (2) a^2b^2c^21\tag{2} a2b2c21(2)   可以得到平面参数 a…