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,改需求改的我沒心思寫博客了

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