C#上位机与三菱PLC的通信11---开发自己的通讯工具软件(WPF版)

1、先看颜值

2、开始干

1、创建项目

2、引入前面的通讯库

 创建目录将前面生成的通讯库dll文件复制到项目的目录

本项目引入dll文件

 

 3、创建命令基类

RelayCommand.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MitsubishiMcToolWPF.Common
{
    /// <summary>
    /// 命令实现类
    /// </summary>
    public class RelayCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        /// <summary>
        /// 要执行的操作
        /// </summary>
        private Action<object> executeActions;
        /// <summary>
        /// 是否可以执行的委托
        /// </summary>
        private Func<object, bool> canExecuteFunc;
        /// <summary>
        /// 构造函数 无参构造
        /// </summary>
        public RelayCommand() { }
        /// <summary>
        /// 通过执行的委托构造
        /// </summary>
        /// <param name="execute"></param>
        public RelayCommand(Action<object> execute) : this(execute, null)
        {

        }
        /// <summary>
        /// 通过执行的操作与是否可执行的委托
        /// </summary>
        /// <param name="execute">要执行的操作</param>
        /// <param name="canExecute">是否可以被执行</param>
        public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
        {
            this.executeActions = execute;
            this.canExecuteFunc = canExecute;
        }

        /// <summary>
        /// 命令是否可以执行
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(object parameter)
        {
            if (canExecuteFunc != null)
                return this.canExecuteFunc(parameter);
            else
                return true;
        }

        /// <summary>
        /// 要执行的操作
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(object parameter)
        {
            if (executeActions == null)
                return;
            this.executeActions(parameter);
        }

        /// <summary>
        /// 执行CanExecuteChanged事件
        /// </summary>
        public void OnCanExecuteChanged()
        {
            this.CanExecuteChanged?.Invoke(this, new EventArgs());
        }
    }
}

 4、创建PLC实体类

PLCMemoryModel.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MitsubishiMcToolWPF.Model
{
    /// <summary>
    /// PLC内存模型类
    /// </summary>
    public class PLCMemoryModel
    {
        /// <summary>
        /// 存储区
        /// </summary>
        public string Area { get; set; } = "";
        /// <summary>
        /// 地址
        /// </summary>

        public string Address { get; set; } = "";
        /// <summary>
        /// 数据类型
        /// </summary>

        public string DataType { get; set; } = "";
        /// <summary>
        /// 读取或写入数据
        /// </summary>

        public string Count { get; set; } = "";
    }
}

 5、添加资源字典,即样式文件

CommonResource.xaml完整代码

 <!--读取写入Button按钮样式--> 
 <Style x:Key="ButtonStyle" TargetType="Button">
     <Setter Property="Background" Value="#3F85FF"></Setter>
     <Setter Property="Foreground" Value="White"></Setter>
     <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
     <Setter Property="Margin" Value="5"></Setter>
     <Setter Property="Height" Value="90"></Setter>
     <Setter Property="FontSize" Value="16"></Setter>
     <!--模板的样式-->
     <Setter Property="Template">
         <Setter.Value>
             <!--Button单选按钮样式-->
             <ControlTemplate TargetType="Button">
                 <Grid >
                     <Border Background="{TemplateBinding Background}" CornerRadius="5" >
                         <TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                     </Border>
                 </Grid>
                 <ControlTemplate.Triggers>
                     <!--鼠标放上去时的触发器-->
                     <Trigger Property="IsMouseOver" Value="True">
                         <Setter Property="Background" Value="#1E5FD1" ></Setter>
                     </Trigger>
                 </ControlTemplate.Triggers>

             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>
 
 <!--连接断开按钮样式-->
 <Style x:Key="ConnStyle" TargetType="Button">
     <Setter Property="Background" Value="#3F8666"></Setter>
     <Setter Property="Foreground" Value="White"></Setter>
     <Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
     <Setter Property="Margin" Value="5"></Setter>
     <Setter Property="Height" Value="60"></Setter>
     <Setter Property="FontSize" Value="16"></Setter>
     <!--模板的样式-->
     <Setter Property="Template">
         <Setter.Value>
             <!--Button单选按钮样式-->
             <ControlTemplate TargetType="Button">
                 <Grid >
                     <Border Background="{TemplateBinding Background}" CornerRadius="5" >
                         <TextBlock Margin="10 5 10 5" Text="{TemplateBinding Content}" FontSize="{TemplateBinding FontSize}" HorizontalAlignment="Center" VerticalAlignment="Center"></TextBlock>
                     </Border>
                 </Grid>
                 <ControlTemplate.Triggers>
                     <!--鼠标放上去时的触发器-->
                     <Trigger Property="IsMouseOver" Value="True">
                         <Setter Property="Background" Value="#1E5FD1" ></Setter>
                     </Trigger>
                 </ControlTemplate.Triggers>
             </ControlTemplate>
         </Setter.Value>
     </Setter>
 </Style>


 <!--TextBox默认样式-->
 <Style TargetType="{x:Type TextBox}" x:Key="txtTextBoxStyle">
     <Setter Property="Width" Value="150"/>
     <Setter Property="Height" Value="25"/>
     <Setter Property="BorderBrush" Value="#FF105190"/>
     <Setter Property="BorderThickness" Value="1"/>
     <Setter Property="Margin" Value="2,0"/>
     <Setter Property="VerticalContentAlignment" Value="Center"/>
     <Setter Property="Background">
         <Setter.Value>
             <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                 <GradientStop Color="White" Offset="0"/>
                 <GradientStop Color="#FFE4E4E4" Offset="1"/>
             </LinearGradientBrush>
         </Setter.Value>
     </Setter>
 </Style>

 <!--TextBlock默认样式-->
 <Style TargetType="{x:Type TextBlock}" x:Key="txtTextBlockStyle">
     <Setter Property="Margin" Value="1"/>
     <Setter Property="Height" Value="15"/>
 </Style>

 <!--页面下拉框样式-->
 <LinearGradientBrush x:Key="ComboBox.Static.Background" EndPoint="0,1" StartPoint="0,0">
     <GradientStop Color="White" Offset="0"/>
     <GradientStop Color="#FFE4E4E4" Offset="1"/>
 </LinearGradientBrush>
 <SolidColorBrush x:Key="ComboBox.Static.Border" Color="#FF105190"/>

 <!--combox默认样式-->
 <Style x:Key="cboStyle" TargetType="{x:Type ComboBox}">
     <Setter Property="Background" Value="{StaticResource ComboBox.Static.Background}"/>
     <Setter Property="BorderBrush" Value="{StaticResource ComboBox.Static.Border}"/>
     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
     <Setter Property="Width" Value="150"/>
     <Setter Property="Height" Value="25"/>
     <Setter Property="BorderThickness" Value="1"/>
     <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
     <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
     <Setter Property="Padding" Value="6,3,5,3"/>
     <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
     <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
     <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
 </Style>

 

 6、创建viewmodel

viewmodel是视图模型,wpf采用的是mvvm的渲染模式,即控件绑定对象的属性,属性发生更改时,驱动控件的数据显示,而控件动作是由命令command执行

1、模型基类

ViewModelBase.cs代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using static MitsubishiMcToolWPF.MsgBoxWindow;

namespace MitsubishiMcToolWPF.ViewModel
{
    /// <summary>
    /// 视图模型基类
    /// </summary>
    public class ViewModelBase : INotifyPropertyChanged
    {
        /// <summary>
        /// 属性值发生更改时触发
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;



        /// <summary>
        /// 执行更改
        /// C#5.0中的新特性CallerMemberName
        /// </summary>
        /// <param name="propertyName"></param>
        protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }


        /// <summary>
        /// 成功消息提示
        /// </summary>
        /// <param name="message"></param>
        /// <param name="title"></param>
        /// <param name="buttons"></param>
        public void ShowMessage(string message, string title = "提示", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK)
        {
            Show(message, title, buttons, CustomMessageBoxIcon.Infomation);
        }

        /// <summary>
        /// 错误消息框
        /// </summary>
        /// <param name="message"></param>
        /// <param name="title"></param>
        /// <param name="buttons"></param>
        public void ShowError(string message, string title = "错误", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK)
        {
            Show(message, title, buttons, CustomMessageBoxIcon.Error);
        }

        /// <summary>
        /// 询问消息框
        /// </summary>
        /// <param name="message"></param>
        /// <param name="title"></param>
        /// <param name="buttons"></param>
        /// <returns></returns>
        public CustomMessageBoxResult ShowQuestion(string message, string title = "询问", CustomMessageBoxButton buttons = CustomMessageBoxButton.OKCancel)
        {
            return Show(message, title, buttons, CustomMessageBoxIcon.Question);
        }



    }
}

 2、主页模型mainviewmodel

MainViewModel.cs代码

 

using Mitsubishi.Communication.MC.Mitsubishi;
using MitsubishiMcToolWPF.Common;
using MitsubishiMcToolWPF.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace MitsubishiMcToolWPF.ViewModel
{
    /// <summary>
    /// 视图模型
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        /// <summary>
        /// mctcp对象
        /// </summary>
        A3E mctcp;

        #region 属性

        PLCMemoryModel readPLCModel = SetInitModel();
        /// <summary>
        /// 读取PLC
        /// </summary>
        public PLCMemoryModel ReadPLCModel
        {
            get { return readPLCModel; }
            set
            {
                readPLCModel = ReadPLCModel;
                OnPropertyChanged();//属性通知
            }
        }

        PLCMemoryModel writePLCModel = SetInitModel();
        /// <summary>
        /// 写入PLC
        /// </summary>
        public PLCMemoryModel WritePLCModel
        {
            get { return writePLCModel; }
            set
            {
                writePLCModel = WritePLCModel;
                OnPropertyChanged();
            }
        }
        /// <summary>
        /// 初始化页面参数
        /// </summary>
        /// <returns></returns>
        private static PLCMemoryModel SetInitModel()
        {
            PLCMemoryModel model = new PLCMemoryModel();
            model.Area = "D";
            model.DataType = "short";
            model.Address = "100";
            model.Count = "1";
            return model;
        }

        private string hostName = "192.168.1.7";
        /// <summary>
        /// PLC地址
        /// </summary>
        public string HostName
        {
            get
            {
                return hostName;
            }
            set
            {
                hostName = value;
            }
        }

        private string hostPort = "6000";
        /// <summary>
        /// PLC端口
        /// </summary>
        public string HostPort
        {
            get { return hostPort; }
            set
            {
                hostPort = value;
            }
        }


        /// <summary>
        /// 存储区下拉框数据源
        /// </summary>
        public List<string> CboCustTypes
        {
            get
            {
                return new List<string>() { "D", "X", "Y", "M", "R", "S", "TS" };
            }
        }

        /// <summary>
        /// 数据类型
        /// </summary>
        public List<string> CboCustDatas
        {
            get
            {
                return new List<string>() { "short", "float", "bool" };
            }
        }

        private string readWords = "";
        /// <summary>
        /// 读数结果
        /// </summary>
        public string ReadWords
        {
            get { return readWords; }
            set
            {
                readWords = value;
                OnPropertyChanged();
            }
        }
        private string writeWords = "";
        /// <summary>
        /// 写入数据
        /// </summary>
        public string WriteWords
        {
            get { return writeWords; }
            set
            {
                writeWords = value;
                OnPropertyChanged();
            }
        }

        private string connectWords = "当前未连接";
        /// <summary>
        /// 连接状态
        /// </summary>
        public string ConnectWords
        {
            get { return connectWords; }
            set
            {
                connectWords = value;
                OnPropertyChanged();
            }
        }
        #endregion

        #region 命令

        /// </summary>
        /// <summary>
        ///连接按钮的命令 
        /// </summary>
        public ICommand ConnCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    var name = HostName;
                    var port = HostPort;
                    mctcp = new A3E(name, short.Parse(port));// 创建连接 
                    var result = mctcp.Connect();// 开始连接PLC
                    if (!result.IsSuccessed)
                    {
                        ShowError(result.Message, "错误");
                        return;
                    }
                    ConnectWords = "PLC已连接";
                    ShowMessage("PLC连接成功", "提示");
                });
            }
        }


        /// </summary>
        /// <summary>
        ///断开按钮的命令 
        /// </summary>
        public ICommand CloseCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    if (mctcp == null)
                    {
                        ShowError("PLC没有连接,不能断开", "错误");
                        return;
                    }
                    mctcp = null;
                    ConnectWords = "PLC已断开";
                });
            }
        }


        /// </summary>
        /// <summary>
        /// 读取按钮的命令 
        /// </summary>
        public ICommand ReadCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    ReadWords = "";
                    var d = ReadPLCModel;
                    if (mctcp == null)
                    {
                        ShowError("PLC未连接,不能读取数据", "错误");
                        return;
                    }
                    //内存地址
                    string plcAddr = ReadPLCModel.Area + ReadPLCModel.Address;
                    //读取数量
                    short readCount = short.Parse(ReadPLCModel.Count);
                    //数据类型
                    string dataType = ReadPLCModel.DataType;
                    switch (dataType)
                    {
                        case "short":
                            var datas2 = mctcp.Read<short>(plcAddr, readCount);
                            if (!datas2.IsSuccessed)
                            {
                                ShowMessage(datas2.Message, "提示");
                                return;
                            }
                            ReadWords = string.Join(",", datas2.Datas);
                            break;
                        case "float":
                            var datas3 = mctcp.Read<float>(plcAddr, readCount);
                            if (!datas3.IsSuccessed)
                            {
                                ShowMessage(datas3.Message, "提示");
                                return;
                            }
                            ReadWords = string.Join(",", datas3.Datas);
                            break;
                        case "bool":
                            var datas4 = mctcp.Read<bool>(plcAddr, readCount);
                            if (!datas4.IsSuccessed)
                            {
                                ShowMessage(datas4.Message, "提示");
                                return;
                            }
                            ReadWords = string.Join(",", datas4.Datas);
                            break;
                    }
                });
            }
        }


        /// </summary>
        /// <summary>
        /// 写入按钮的命令处理
        /// </summary>
        public ICommand WriteCommand
        {
            get
            {
                return new RelayCommand(o =>
                {
                    if (mctcp == null)
                    {
                        ShowError("PLC未连接,不能写入数据", "错误");
                        return;
                    }
                    var d = WritePLCModel;
                    //内存地址
                    string plcAddr = WritePLCModel.Area + WritePLCModel.Address;
                    //写入数量 
                    ushort writeCount = ushort.Parse(WritePLCModel.Count);
                    //数据类型
                    string dataType = WritePLCModel.DataType;
                    //实际数量
                    string objWriteVals = WriteWords;
                    ushort objWCount = (ushort)objWriteVals.Split(',').Length;
                    //实际数量与要求数量不一致,不允许操作
                    if (writeCount != objWCount)
                    {
                        ShowError("写入值的数量不正确!");
                        return;
                    }
                    List<string> vals = objWriteVals.Split(',').ToList();
                    switch (dataType)
                    {
                        case "short":
                            //实际数值转换成list集合 short类型
                            List<short> objshort = new List<short>();
                            vals.ForEach((x) =>
                            {
                                objshort.Add(short.Parse(x));
                            });
                            var finish2 = mctcp.Write<short>(objshort, plcAddr);
                            if (finish2.IsSuccessed)
                            {
                                ShowMessage("写入成功", "提示");
                            }
                            break;
                        case "float":
                            //实际数值转换成list集合 float
                            List<float> objfloat = new List<float>();
                            vals.ForEach((x) =>
                            {
                                objfloat.Add(float.Parse(x));
                            });
                            var finish3 = mctcp.Write<float>(objfloat, plcAddr);
                            if (finish3.IsSuccessed)
                            {
                                ShowMessage("写入成功", "提示");
                            }
                            break;
                        case "bool":
                            //实际数值转换成list集合bool
                            List<bool> objbool = new List<bool>();
                            vals.ForEach((x) =>
                            {
                                if (x == "1")
                                {
                                    objbool.Add(true);
                                }
                                else
                                {
                                    objbool.Add(false);
                                }
                            });
                            var finish4 = mctcp.Write<bool>(objbool, plcAddr);
                            if (finish4.IsSuccessed)
                            {
                                ShowMessage("写入成功", "提示");
                            }
                            break;
                    }
                });
            }
        }
        #endregion

    }
}

7、主界面布局

MainWindow.xaml完整代码

<Window x:Class="MitsubishiMcToolWPF.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:MitsubishiMcToolWPF.ViewModel"
        mc:Ignorable="d"   
        FontSize="13" FontFamily="Microsoft YaHei"  ResizeMode="CanMinimize" Title="三菱PLC通讯工具" FontWeight="ExtraLight" WindowStartupLocation="CenterScreen"  Height="450" Width="880" Name="mainWin"  >
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid   ShowGridLines="true">
        <Grid.RowDefinitions>
            <RowDefinition Height="62"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <!--第一行标题-->
        <Grid Grid.Row="0" Background="BlanchedAlmond">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Image Grid.Column="0" Source="/imgs/log1.png"  Width="60" Height="60" Margin="20,0" />
            <TextBlock Grid.Column="1"   Text="三菱MC协议通讯调试助手(Qna-3E模式)" FontSize="23" VerticalAlignment="Center"  FontWeight="Bold" />
        </Grid>

        <!--第二行信息-->
        <Grid Grid.Row="1" Margin="0 10 0 0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200"/>
                <ColumnDefinition Width="4"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <!--第一列PLC参数-->
            <StackPanel Grid.Column="0" Margin="20">
                <TextBlock Text="PLC地址"/>
                <TextBox   Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Text="{Binding HostName}"  />
                <TextBlock Text="端口号" Margin="0,10,0,0"/>
                <TextBox  Height="30" VerticalContentAlignment="Center" Padding="5,0" Margin="0,10" Text="{Binding HostPort}"  />
                <Button Content="连接" Margin="0,30,0,0" Height="30"   Command="{Binding ConnCommand}"  Style="{StaticResource ConnStyle}" />
                <Button Content="断开" Margin="0,10" Height="30"  Command="{Binding CloseCommand}"  Style="{StaticResource ConnStyle}"/>
                <TextBlock  Text="{Binding ConnectWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Margin="0,10,0,0"  Foreground="Blue"/>
            </StackPanel>
            <!--第二列分隔线-->
            <GridSplitter Grid.Column="1" Background="#4490AC" Width="2" Height="450" Margin="0 -11 0 0"></GridSplitter>
            <!--第三列操作区-->
            <Grid Grid.Column="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="60"/>
                    <RowDefinition Height="80"/>
                    <RowDefinition Height="30"/>
                    <RowDefinition Height="60"/>
                    <RowDefinition Height="80"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="10">
                    <TextBlock     Text="存储区:"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 0 0 0" ></TextBlock>
                    <ComboBox  ItemsSource="{Binding CboCustTypes}" SelectedValue="{Binding  ReadPLCModel.Area}"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="数据类型:"  Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <ComboBox     ItemsSource="{Binding CboCustDatas}" SelectedValue="{Binding ReadPLCModel.DataType}"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="地址:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox    Text="{Binding ReadPLCModel.Address}"  Width="100"  Style="{StaticResource  txtTextBoxStyle}" />
                    <TextBlock   Text="数量:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox    Text="{Binding ReadPLCModel.Count}"  Width="60" Style="{StaticResource  txtTextBoxStyle}"  />
                    <Button Content="读取" Height="30" Width="100"  Command="{Binding ReadCommand}" CommandParameter="{Binding ElementName=loginWin}" Style="{StaticResource ButtonStyle}"  />
                </StackPanel>

                <StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10">
                    <TextBlock Text="读取结果(多个数据之间用逗号隔开)"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 3 0 9"></TextBlock>
                    <TextBox   Text="{Binding ReadWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="616" Style="{StaticResource  txtTextBoxStyle}"  Margin="-23,0,0,0"   />
                </StackPanel>

                <StackPanel Orientation="Horizontal"  Grid.Row="2"  Grid.Column="0" Grid.ColumnSpan="2" Background="#4490AC" Width="706" Height="2" Margin="-1,0,0,0"></StackPanel>

                <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10">
                    <TextBlock     Text="存储区:" Style="{StaticResource  txtTextBlockStyle}" Margin="0 0 0 0"></TextBlock>
                    <ComboBox    ItemsSource="{Binding CboCustTypes}" SelectedValue="{Binding WritePLCModel.Area }"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="数据类型:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <ComboBox     ItemsSource="{Binding CboCustDatas}" SelectedValue="{Binding WritePLCModel.DataType }"  Width="70"  Style="{StaticResource cboStyle}"></ComboBox>
                    <TextBlock   Text="地址:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox   Text="{Binding  WritePLCModel.Address }"  Width="100"  Style="{StaticResource  txtTextBoxStyle}"  />
                    <TextBlock   Text="数量:" Style="{StaticResource  txtTextBlockStyle}" ></TextBlock>
                    <TextBox    Text="{Binding WritePLCModel.Count}"  Width="60"   Style="{StaticResource  txtTextBoxStyle}"  />
                    <Button Content="写入" Height="30" Width="100"   Command="{Binding WriteCommand}" CommandParameter="{Binding ElementName=loginWin}" Style="{StaticResource ButtonStyle}" />
                </StackPanel>

                <StackPanel Orientation="Vertical" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10">
                    <TextBlock   Text="写入数据(多个数据之间用逗号隔开)" Style="{StaticResource  txtTextBlockStyle}"  Margin="0 3 0 9" ></TextBlock>
                    <TextBox    Text="{Binding WriteWords ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="616" Style="{StaticResource  txtTextBoxStyle}"  Margin="-23,0,0,0"  />
                </StackPanel>

            </Grid>
        </Grid>
    </Grid>
</Window>

 

 8、启动MC服务器

 9、异常错误处理

 

10、操作测试

1、连接PLC

2、读取数据,short,float,bool

 

3、写入数据,short,float

 写入short

写入float

 

3、小结

 

走过路过不要错过,点赞关注收藏又圈粉,共同致富。

欢迎抄袭,复制,分享,转载,学习,截图..............

欢迎抄袭,复制,分享,转载,学习,截图..............

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

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

相关文章

【EI会议征稿通知】第四届生物医学与生物信息工程国际学术会议(ICBBE 2024)

第四届生物医学与生物信息工程国际学术会议&#xff08;ICBBE 2024&#xff09; The 4th International Conference on Biomedicine and Bioinformatics Engineering 由河南大学主办&#xff0c;中州实验室、河南大学基础医学院、河南大学郑州校区学术发展部共同承办的第四届生…

docker部署seata1.6.0

docker部署seata1.6.0 Seata 是 阿里巴巴 开源的 分布式事务中间件&#xff0c;解决 微服务 场景下面临的分布式事务问题。需要先搭建seata服务端然后与springcloud的集成以实现分布式事务控制的过程 &#xff0c;项目中只需要在远程调用APi服务的方法上使用注解 GlobalTransa…

npm install 失败,需要node 切换到 对应版本号

npm install 失败 原本node 的版本号是16.9&#xff0c;就会报以上错误 node版本问题了&#xff0c;我切到这个版本&#xff0c;报同样的错。降一下node&#xff08;14.18&#xff09;版本就好了 具体的方法&#xff1a;&#xff08;需要在项目根目录下切换&#xff09; 1. …

动力气象-斜压发展

前言 斜压发展 天气尺度扰动发展通常被称为锋生&#xff0c;强调的是相对涡度在天气尺度系统发展过程中的作用。 具体而言&#xff0c;讨论的是天气尺度扰动增长过程中平均气流的动力学不稳定起到的作用。 7.1静力不稳定性 概念&#xff1a; 如果进入纬向平均流场的小尺度扰…

男性美颜SDK解决方案,专属男性美化新体验

随着科技的发展&#xff0c;美颜技术已广泛应用于摄影、社交、直播等领域&#xff0c;满足了用户对美的追求。然而&#xff0c;传统的美颜算法往往更偏向于女性用户&#xff0c;忽视了男性用户对于自然、真实美的需求。美摄科技针对这一市场痛点&#xff0c;推出了专为男性设计…

ArcgisForJS如何实现添加含图片样式的点要素?

文章目录 0.引言1.加载底图2.获取点要素的坐标3.添加含图片样式的几何要素4.完整实现 0.引言 ArcGIS API for JavaScript 是一个用于在Web和移动应用程序中创建交互式地图和地理空间分析应用的库。本文在ArcGIS For JavaScript中使用Graphic对象来创建包含图片样式的点要素。 …

深入浅出JVM(六)之前端编译过程与语法糖原理

本篇文章将围绕Java中的编译器&#xff0c;深入浅出的解析前端编译的流程、泛型、条件编译、增强for循环、可变长参数、lambda表达式等语法糖原理 编译器与执行引擎 编译器 Java中的编译器不止一种&#xff0c;Java编译器可以分为&#xff1a;前端编译器、即时编译器和提前编…

【鸿蒙 HarmonyOS 4.0】ArkTS开发语言

一、背景 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 二、基本语法 2.1、基本语法介绍 ArkTS的基本组成&#xff0c;资料来自…

查找算法/搜索 | 二分法(python)

Hi&#xff0c;大家好&#xff0c;我是半亩花海。近期在学习算法与数据结构相关知识&#xff0c;纯纯小白&#xff0c;欢迎一起交流呀。打算从算法学起&#xff0c;首先学习查找算法&#xff08;搜索&#xff09;中的二分法&#xff0c;我使用的是 python 语言进行学习。本算法…

【QT-lineEidte动画效果

QT-lineEidte动画效果 一、演示效果二、核心代码三、下载链接 一、演示效果 二、核心代码 #ifndef DynamicUnderlineLineEdit_H #define DynamicUnderlineLineEdit_H#include <QWidget> #include <QLineEdit> #include <QPainter> #include <QPaintEvent…

【学习iOS高质量开发】——协议与分类

文章目录 一、通过委托与数据源协议进行对象间通信1.委托模式2.要点 二、将类的实现代码分散到便于管理的数个分类之中1.如何实现2.要点 三、总是为第三方类的分类名称加前缀1.为什么总是为第三方类的分类名称加前缀2.要点 三、勿在分类中声明属性1.勿在分类中声明属性的原因2.…

【最新Dubbo3深入理解】Dubbo3中的SPI机制以及IOC、AOP

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

MFC 配置Halcon

1.新建一个MFC 工程&#xff0c;Halcon 为64位&#xff0c;所以先将工程改为x64 > VC 目录设置包含目录和库目录 包含目录 库目录 c/c ->常规 链接器 ->常规 > 链接器输入 在窗口中添加头文件 #include "HalconCpp.h" #include "Halcon.h"…

canvas水波纹效果,jquery鼠标水波纹插件

canvas水波纹效果&#xff0c;jquery鼠标水波纹插件 效果展示 jQuery水波纹效果&#xff0c;canvas水波纹插件 HTML代码片段 <div class"scroll04wrap"><h3>发展历程</h3><div class"scroll04"><p>不要回头&#xff0c;一…

移动硬盘误删的文件还能找回来吗?1分钟弄清答案!

“想问问大家如果移动硬盘里保存了很多文件&#xff0c;但上次使用时不小心将部分文件删除了&#xff0c;还有机会找回误删的文件吗&#xff1f;应该怎么进行误删文件的恢复呢&#xff1f;” 在数字化时代&#xff0c;移动硬盘成为了我们存储和传输数据的重要工具。然而&#x…

外泌体相关基因肝癌临床模型预测——2-3分纯生信文章复现——02.数据格式整理(1)

内容如下&#xff1a; 1.外泌体和肝癌TCGA数据下载 2.数据格式整理 3.差异表达基因筛选 4.预后相关外泌体基因确定 5.拷贝数变异及突变图谱 6.外泌体基因功能注释 7.LASSO回归筛选外泌体预后模型 8.预后模型验证 9.预后模型鲁棒性分析 10.独立预后因素分析及与临床的…

【Appium UI自动化】pytest运行常见错误解决办法

通过Appium工具录制代码在pycharm上运行报错&#xff1a; 错误一&#xff1a; 1.提示 setup() 方法运行 error failed 解决办法&#xff1a;未创建 init __ 方法&#xff0c;创建一个空的__init.py文件就解决了。 原因&#xff1a; 错误二&#xff1a; 2.运行代码&#xff…

Rabbitmq入门与应用(四)-RabbitMQ常见模式

RabbitMQ常见Queue模式 简单模式 点对点模式&#xff0c;一个生产者一个消费者 生产者将消息发送到队列&#xff0c;消费者从队列中获取消息&#xff0c;队列是存储消息的缓冲区。 查看管理端效果 序列化解决方案 基于java序列化基于Json Bean public MessageConverter mess…

【Java从入门到精通】Java Character 类

Java Character 类 Character 类用于对单个字符进行操作。 Character 类在对象中包装一个基本类型 char 的值 实例 char ch a;// Unicode 字符表示形式 char uniChar \u039A; // 字符数组 char[] charArray { a, b, c, d, e }; 然而&#xff0c;在实际开发过程中&#xf…

利用Python email的MIMEBase及MIMEApplication发送邮件附件

**MIMEBase、 MIMEApplication背景知识点总结** MIMEBase 和 MIMEApplication 都是用于创建 MIME 消息的类&#xff0c;但它们之间有一些异同点。 异同点如下&#xff1a; 用途&#xff1a; MIMEBase 是一个基类&#xff0c;用于表示任何类型的 MIME 消息部分。它提供了一种通…