WPF+Modbus 第一课,MVVM模式读取,写入

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

最近在知乎,看了很多提问,涉及到就业,裁员,经济等,不看不知道,越看越头疼,知乎上很多人提问

毕业生就业如何难,2023年裁员如何严重,35岁的中年危机,程序员被裁员后找不到工作该,经济如何差等话题

哎,这让我这个35岁的老程序员感到莫大的压力,我时常想,如果我离开了现在的公司,我能找到工作吗?多久能找到工作?如果找不到工作,我能干什么?

35岁,本是经验技术相对比较成熟的阶段,更是上有老下有小的年龄段,也是花钱多的时候,如果在这个年龄段没了收入,该多么绝望......,但没办法,世界就是如此,它不会顾及你的感受,生存法则而已

言归正传,在开始正文之前,小伙伴们看下知乎上提的一个话题:35岁了,还有必要继续卷技术吗? 你们认为呢?

本来鄙人也不打算继续内卷了,但中年危机的压迫感,迫使我不得不拿起手中的枪,继续战斗!我本是做web开发的,但C#语言似乎CS开发岗位更多,而且似乎不受年龄限制,大不了40岁进厂做工控机开发呗,再说了,厂里妹子不是多么,挺好的

1、下载Modbus Slave软件

下载Modbus Slave软件用于模拟Modbus从站设备,下载地址自行必应,关于Modbus Slave的介绍,大家可参考:Modbus Slave 

2、新建wpf项目--NetFrm4.8版本

2.1、 Nuget 引入 NModbus

 2.2、xaml如下

<Window x:Class="WpfApp.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:WpfApp" xmlns:models="clr-namespace:WpfApp.Models" d:DataContext="{d:DesignInstance Type=models:MainWindowModel}"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel>
            <TextBlock Text="温度"/>
            <TextBox   Text="{Binding wendu}" /> 


            <TextBlock Text="湿度"/>
            <TextBox Text="{Binding shidu}" />

            <Button Content="点击" Command="{Binding BtnCommand}"></Button>
        </StackPanel>
    </Grid>
</Window>
View Code

界面很丑陋,如下

 这里说明几点

mvvm 的 viewModel 命名空间

xmlns:models="clr-namespace:WpfApp.Models"

数据上下文

d:DataContext="{d:DesignInstance Type=models:MainWindowModel}"

2.3、MainWindow主程序

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowModel();
           
        }

主程序中声明数据上下文

2.4、MainWindow 数据上下文viewModel

新建 MainWindowModel,使其继承自 INotifyPropertyChanged,并实现INotifyPropertyChanged接口

1、先搞定双向绑定

xaml 中的文本框绑定了两个属性,分别为温度、湿度,因此,我们需要在viewModel中增加wendu属性和shidu属性,如下

 public class MainWindowMod : INotifyPropertyChanged
    {
        public MainWindowMod()
        {
            this.wendu = 20;
            this.shidu = 80;
        }
        private ushort _wendu;
        public ushort wendu
        {
            get { return this._wendu; }
            set
            {
                this._wendu = value;
                this.OnPropertyChanged("wendu");
            }
        }
        private ushort _shidu;
        public ushort shidu
        {
            get { return this._shidu; }
            set
            {
                this._shidu = value;
                this.OnPropertyChanged("shidu");
            }
        }

        /// <summary>
        /// 用于双向绑定
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
View Code

 此时,就完成了WPF的双向绑定功能

2、搞定按钮单击事件

我们不使用button_click事件,使用 Command 事件来完成点击事件

button 绑定如下:

<Button Content="点击" Command="{Binding BtnCommand}"></Button>

新建继承自ICommand基类

    public class CommandBase : ICommand
    {
        public event EventHandler CanExecuteChanged;

        /// <summary>
        /// 是否可执行
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object parameter)
        {
            return true;
        }

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

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

viewModel 变更如下:

    public class MainWindowMod : INotifyPropertyChanged
    {
        //新建按钮点击事件
        public ICommand BtnCommand { get; set; }

        public MainWindowMod()
        {
            this.wendu = 20;
            this.shidu = 80;
            //执行委托
            BtnCommand = new CommandBase() { action = new Action<object>(DoBtnCommand) };
        }

        /// <summary>
        /// 按钮click执行
        /// </summary>
        /// <param name="obj"></param>
        public void DoBtnCommand(object obj)
        {
            this.shidu = 888;
        }
        private ushort _wendu;
        public ushort wendu
        {
            get { return this._wendu; }
            set
            {
                this._wendu = value;
                this.OnPropertyChanged("wendu");
            }
        }
        private ushort _shidu;
        public ushort shidu
        {
            get { return this._shidu; }
            set
            {
                this._shidu = value;
                this.OnPropertyChanged("shidu");
            }
        }

        /// <summary>
        /// 用于双向绑定
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

2.5、增加ModBus部分

using NModbus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows.Input;

namespace WpfApp.Models
{
    public class MainWindowModel : INotifyPropertyChanged
    {
        private static ModbusFactory modbusFactory;
        private static IModbusMaster master;
        public ICommand BtnCommand { get; set; }
        public MainWindowModel()
        {
            //初始化modbusmaster
            modbusFactory = new ModbusFactory();
            //在本地测试 所以使用回环地址,modbus协议规定端口号 502
            master = modbusFactory.CreateMaster(new TcpClient("127.0.0.1", 502));
            //设置读取超时时间
            master.Transport.ReadTimeout = 2000;
            master.Transport.Retries = 2000;
            Task.Run(async () =>
            {
                while (true)
                {
                    await Task.Delay(500);

                    this.wendu = master.ReadHoldingRegisters(1, 0, 1)[0];
                    this.shidu = master.ReadHoldingRegisters(1, 1, 1)[0];
                }
            });

            BtnCommand = new CommandBase() { action = new Action<object>(DoBtnCommand) };
        }

        public void DoBtnCommand(object obj)
        {
            master.WriteSingleRegister(1, 0, 888);
        }
        private ushort _wendu;
        public ushort wendu
        {
            get { return this._wendu; }
            set
            {
                this._wendu = value;
                this.OnPropertyChanged("wendu");
            }
        }
        private ushort _shidu;
        public ushort shidu
        {
            get { return this._shidu; }
            set
            {
                this._shidu = value;
                this.OnPropertyChanged("shidu");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this,  new PropertyChangedEventArgs(propertyName));
            }
        }


    }
}
View Code

over,改需求改的我没心思写博客了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章