C#上位机与欧姆龙PLC的通信10----开发专用的通讯工具软件(WPF版)

本文主要是介绍C#上位机与欧姆龙PLC的通信10----开发专用的通讯工具软件(WPF版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、介绍

上节开发了一个winform版的通讯测试工具,这节再搞个wpf版的,wpf是什么?请自行百度,也可以看前面的博客,WPF真入门教程,wpf的界面效果是比winform漂亮,因为wpf使用了web项目中的css样式来美化界面,在这个例子中用到wpf的控件,资源样式,命令绑定等,采用的是mvvm的渲染模式,界面如图:

前面的winform界面:

 2、开工干

2.1 创建wpf项目

2.2 创建目录及PLC模型类对象

 2.3 创建自定义的消息弹窗

MsgBoxWindow.xaml代码

<Window x:Class="OmronFinsWPFApp.MsgBoxWindow"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:OmronFinsWPFApp"mc:Ignorable="d"Title="消息框" Height="200" Width="420" WindowStartupLocation="CenterScreen" BorderThickness="1,0,1,1" ResizeMode="NoResize" WindowStyle="None" AllowsTransparency="True" Background="Transparent"><Window.Resources><Style TargetType="Button" x:Key="msgbtnStyle"><Setter Property="Width" Value="60"/><Setter Property="Height" Value="25"/><Setter Property="Margin" Value="10,0,15,0"/></Style></Window.Resources><Grid Background="Transparent" MouseLeftButtonDown="Grid_MouseLeftButtonDown" ><Border BorderBrush="#FFA9AEB1"  BorderThickness="2" CornerRadius="10" Margin="5"><Border.Effect><DropShadowEffect BlurRadius="10" Color="#FFB8BBC8" Direction="300" ShadowDepth="2"/></Border.Effect><Border.Background><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="#FFFBFBFB" Offset="0.16"/><GradientStop Color="#FFB4D8E2" Offset="0.986"/></LinearGradientBrush></Border.Background><Grid x:Name="grid" Margin="5"><Grid.RowDefinitions><RowDefinition Height="30"/><RowDefinition/><RowDefinition Height="50" /></Grid.RowDefinitions><Grid Grid.Row="0" Background="Transparent"><Border  Background="Transparent"  ><Grid><TextBlock Text="{Binding MessageTitle}" HorizontalAlignment="Left"  Height="25" Width="200" VerticalAlignment="Center" Margin="5,0" /><Image Source="imgs/errbtn.jpg" HorizontalAlignment="Right" Margin="0,3,3,2"  MouseLeftButtonDown="Image_MouseLeftButtonDown"/></Grid></Border></Grid><!--显示图片和文本--><StackPanel Grid.Row="1" VerticalAlignment="Center" Orientation="Horizontal"><Image Source="{Binding ImagePath}" Width="30" Height="30" Margin="40,20,20,20"/><TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" TextWrapping="WrapWithOverflow" Width="280" TextAlignment="Left"Text="{Binding MessageBoxText}" FontSize="12"/></StackPanel><!--Button Margin(坐上右下)--><StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right"><Button Content="确 定" Style="{StaticResource msgbtnStyle}" x:Name="OkButton"   IsDefault="True"Visibility="{Binding OkButtonVisibility,Mode=OneWay}" Click="OkButton_Click"/><Button Content="是" Style="{StaticResource msgbtnStyle}"  x:Name="YesButton"  Visibility="{Binding YesButtonVisibility,Mode=OneWay}" Click="YesButton_Click"/><Button Content="否" Style="{StaticResource msgbtnStyle}"  x:Name="NoButton" Visibility="{Binding NoButtonVisibility,Mode=OneWay}" Click="NoButton_Click"/><Button Content="取消" Style="{StaticResource msgbtnStyle}"  x:Name="CancelButton" Visibility="{Binding CancelButtonVisibility}" Click="CancelButton_Click"/></StackPanel></Grid></Border></Grid>
</Window>

 MsgBoxWindow.xaml.cs代码(这是页面MsgBoxWindow.xaml的后台逻辑代码)

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.Shapes;namespace OmronFinsWPFApp
{/// <summary>/// MsgBoxWindow.xaml 的交互逻辑/// </summary>public partial class MsgBoxWindow : Window{public MsgBoxWindow(){InitializeComponent();this.DataContext = this;//所有按钮不显示()OkButtonVisibility = Visibility.Collapsed;CancelButtonVisibility = Visibility.Collapsed;YesButtonVisibility = Visibility.Collapsed;NoButtonVisibility = Visibility.Collapsed;Result = CustomMessageBoxResult.None;}/// <summary>/// 显示按钮类型/// </summary>public enum CustomMessageBoxButton{OK = 1,OKCancel = 2,YesNo = 3,YesNoCancel = 4}/// <summary>/// 消息框返回值/// </summary>public enum CustomMessageBoxResult{None = 0,//用户直接关闭消息框OK = 1,//用户点击了确定按钮Cancel = 2,//用户点击了取消按钮Yes = 3,//用户点击了是按钮No = 4//用户点击了否按钮}/// <summary>/// 图标类型/// </summary>public enum CustomMessageBoxIcon{None = 0,Error = 1,Question = 2,Infomation = 3}#region 页面属性定义/// <summary>/// 消息文本/// </summary>public string MessageBoxText { get; set; }/// <summary>/// 消息框标题/// </summary>public string MessageTitle { get; set; }/// <summary>/// 图标路径/// </summary>public string ImagePath { get; set; }/// <summary>/// 显示确定/// </summary>public Visibility OkButtonVisibility { get; set; }/// <summary>/// 显示取消/// </summary>public Visibility CancelButtonVisibility { get; set; }/// <summary>/// 显示是/// </summary>public Visibility YesButtonVisibility { get; set; }/// <summary>/// 显示否/// </summary>public Visibility NoButtonVisibility { get; set; }/// <summary>/// 消息框返回值/// </summary>public CustomMessageBoxResult Result { get; set; }#endregionprivate void CancelButton_Click(object sender, RoutedEventArgs e){Result = CustomMessageBoxResult.Cancel;this.Close();}private void NoButton_Click(object sender, RoutedEventArgs e){Result = CustomMessageBoxResult.No;this.Close();}private void YesButton_Click(object sender, RoutedEventArgs e){Result = CustomMessageBoxResult.Yes;this.Close();}private void OkButton_Click(object sender, RoutedEventArgs e){Result = CustomMessageBoxResult.OK;this.Close();}private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){this.Close();}/// <summary>/// 消息框拖动/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){this.DragMove();}/// <summary>/// 显示消息框/// </summary>/// <param name="msgText"></param>/// <param name="title"></param>/// <param name="msgBtn"></param>/// <param name="msgIcon"></param>/// <returns></returns>public static CustomMessageBoxResult Show(string msgText, string title, CustomMessageBoxButton msgBtn, CustomMessageBoxIcon msgIcon){MsgBoxWindow msg = new MsgBoxWindow();msg.Topmost = true;msg.MessageBoxText = msgText;msg.MessageTitle = title;//消息框按钮显示switch (msgBtn){case CustomMessageBoxButton.OK:msg.OkButtonVisibility = Visibility.Visible;break;case CustomMessageBoxButton.OKCancel:msg.OkButtonVisibility = Visibility.Visible;msg.CancelButtonVisibility = Visibility.Visible;break;case CustomMessageBoxButton.YesNo:msg.YesButtonVisibility = Visibility.Visible;msg.NoButtonVisibility = Visibility.Visible;break;case CustomMessageBoxButton.YesNoCancel:msg.YesButtonVisibility = Visibility.Visible;msg.NoButtonVisibility = Visibility.Visible;msg.CancelButtonVisibility = Visibility.Visible;break;default:msg.OkButtonVisibility = Visibility.Visible;break;}switch (msgIcon){case CustomMessageBoxIcon.Infomation:msg.ImagePath = @"imgs/success.jpg";break;case CustomMessageBoxIcon.Error:msg.ImagePath = @"imgs/error.jpg";break;case CustomMessageBoxIcon.Question:msg.ImagePath = @"imgs/question.jpg";break;}msg.ShowDialog();return msg.Result;} }
}

2.4 添加之前的通讯库dll文件,并引用到项目中

2.5 添加目录及命令类RelayCommand

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;namespace OmronFinsWPFApp.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);elsereturn 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());}}
}

2.6 添加视图模型类对象

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 OmronFinsWPFApp.MsgBoxWindow;namespace OmronFinsWPFApp.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);}}
}

 

using Omron.Communimcation.Fins.Omron;
using OmronFinsWPFApp.Common;
using OmronFinsWPFApp.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;namespace OmronFinsWPFApp.ViewModel
{/// <summary>/// 视图模型/// </summary>public class MainViewModel : ViewModelBase{/// <summary>/// finstcp对象/// </summary>FinsTcp finsTcp; 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 = "DM";model.DataType = "ushort";model.Address = "";model.Count = "1";return model;}private string hostName = "192.168.1.4";/// <summary>/// PLC地址/// </summary>public string HostName{get{return hostName;}set{hostName = value;}}private string hostPort = "7788";/// <summary>/// PLC端口/// </summary>public string HostPort{get { return hostPort; }set{hostPort = value;}}/// <summary>/// 存储区下拉框数据源/// </summary>public List<string> CboCustTypes{get{return new List<string>() { "DM", "H", "W", "CIO" };}}/// <summary>/// 数据类型/// </summary>public List<string> CboCustDatas{get{return new List<string>() { "ushort", "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();}}/// </summary>/// <summary>/// 登录按钮的命令处理/// </summary>public ICommand LoginCommand{get{return new RelayCommand(o =>{var name = HostName;var port = HostPort;finsTcp = new FinsTcp(name, Convert.ToInt32(port), 10, 04);// 创建连接 var result = finsTcp.Connect();// 开始连接PLCif (!result.IsSuccessed){ShowError(result.Message, "错误");return;}ShowMessage("PLC连接成功", "提示");ConnectWords = "PLC连接成功";});}}/// </summary>/// <summary>/// 读取按钮的命令处理/// </summary>public ICommand ReadCommand{get{return new RelayCommand(o =>{var d = ReadPLCModel; //内存地址string plcAddr = ReadPLCModel.Area + ReadPLCModel.Address;//读取数量ushort readCount = ushort.Parse(ReadPLCModel.Count);//数据类型string dataType = ReadPLCModel.DataType;switch (dataType){case "ushort":var datas = finsTcp.Read<ushort>(plcAddr, readCount);if (!datas.IsSuccessed){ShowMessage(datas.Message, "提示");return;}ReadWords = string.Join(",", datas.Datas);break;case "short":var datas2 = finsTcp.Read<short>(plcAddr, readCount);if (!datas2.IsSuccessed){ShowMessage(datas2.Message, "提示");return;}ReadWords = string.Join(",", datas2.Datas);break;case "float":var datas3 = finsTcp.Read<float>(plcAddr, readCount);if (!datas3.IsSuccessed){ShowMessage(datas3.Message, "提示");return;}ReadWords = string.Join(",", datas3.Datas);break;case "bool":var datas4 = finsTcp.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 =>{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 "ushort"://实际数值转换成list集合ushort类型List<ushort> objushort = new List<ushort>();vals.ForEach((x) =>{objushort.Add(ushort.Parse(x));});var finish1 = finsTcp.Write(objushort, plcAddr);if (finish1.IsSuccessed){ShowMessage(finish1.Message, "提示");}break;case "short"://实际数值转换成list集合 short类型List<short> objshort = new List<short>();vals.ForEach((x) =>{objshort.Add(short.Parse(x));});var finish2 = finsTcp.Write(objshort, plcAddr);if (finish2.IsSuccessed){ShowMessage(finish2.Message, "提示");}break;case "float"://实际数值转换成list集合 floatList<float> objfloat = new List<float>();vals.ForEach((x) =>{objfloat.Add(float.Parse(x));});var finish3 = finsTcp.Write(objfloat, plcAddr);if (finish3.IsSuccessed){ShowMessage(finish3.Message, "提示");}break;case "bool"://实际数值转换成list集合boolList<bool> objbool = new List<bool>();vals.ForEach((x) =>{if (x == "1"){objbool.Add(true);}else{objbool.Add(false);}});var finish4 = finsTcp.Write(objbool, plcAddr);if (finish4.IsSuccessed){ShowMessage(finish4.Message, "提示");}break;}});}}}
}

2.7 主界面样式

首先添加资源文件

 

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"><!--定义通用的按钮样式--><Style TargetType="{x:Type Button}" x:Key="btnBaseStyle"><Setter Property="Height" Value="22"/><Setter Property="Width" Value="60"/><Setter Property="FontFamily" Value="微软雅黑"/><Setter Property="Margin" Value="3,0"/><Setter Property="FontSize" Value="16"/><Setter Property="FontWeight" Value="Bold"/><Setter Property="Foreground"  Value="Blue"/></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>
</ResourceDictionary>

 使用资源文件 

2.8 主界面布局

 

<Window x:Class="OmronFinsWPFApp.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:OmronFinsWPFApp.ViewModel"mc:Ignorable="d"   WindowStartupLocation="CenterScreen"FontSize="13" FontFamily="Microsoft YaHei" FontWeight="ExtraLight" Title="欧姆龙PLC通讯工具" Height="430" Width="860" Name="loginWin"><Window.DataContext><local:MainViewModel/></Window.DataContext><Grid Background="Honeydew" ShowGridLines="true"><Grid.RowDefinitions><RowDefinition Height="60"/><RowDefinition/></Grid.RowDefinitions><!--第一行标题--><TextBlock Grid.Row="0" Text="C#利用Fins协议实现欧姆龙PLC的数据读写" FontSize="22" VerticalAlignment="Center" Margin="20,0" FontWeight="Bold" /><!--第二行信息--><Grid Grid.Row="1"><Grid.ColumnDefinitions><ColumnDefinition Width="200"/><ColumnDefinition/></Grid.ColumnDefinitions> <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 LoginCommand}" CommandParameter="{Binding ElementName=loginWin}"  /><Button Content="断开" Margin="0,10" Height="30" /><TextBlock  Text="{Binding ConnectWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Margin="0,10,0,0"  Foreground="Blue"/></StackPanel><Grid Grid.Column="1"><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}" ></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 btnBaseStyle}"  /></StackPanel><StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10"><TextBlock Text="读取结果(多个数据之间用逗号隔开)"  Style="{StaticResource  txtTextBlockStyle}" Margin="0 5 0 9"></TextBlock><TextBox   Text="{Binding ReadWords,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="600" Style="{StaticResource  txtTextBoxStyle}"    /></StackPanel><StackPanel Orientation="Horizontal" Margin="5" Grid.Row="2"  Grid.Column="0" Grid.ColumnSpan="2" Background="#4490AC" Width="600"></StackPanel><StackPanel Orientation="Horizontal" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10"><TextBlock     Text="存储区:" Style="{StaticResource  txtTextBlockStyle}" ></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 btnBaseStyle}" /></StackPanel><StackPanel Orientation="Vertical" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2"  Margin="10"><TextBlock   Text="写入数据(多个数据之间用逗号隔开)" Style="{StaticResource  txtTextBlockStyle}" Margin="0 5 0 9" ></TextBlock><TextBox    Text="{Binding WriteWords ,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"  Width="600" Style="{StaticResource  txtTextBoxStyle}"  /></StackPanel></Grid></Grid></Grid>
</Window>

运行起来效果

3、测试软件

3.1 测试PLC连接

3.2 读取dm区100的short类型

3.3 读取h区100的ushort类型

3.4 读取w区100的float类型

3.5 读取cio区100的bool类型

3.6 写入DM区110的short类型

 

 

3.7 写入H区110的ushort类型

3.8 写入W区110的float类型

3.9 写入CIO区110的bool类型

 

全部通讯报文 

4、小结

本例子用到WPF的MVVM模式,不是winform中的按钮点击事件,是后台绑定viewmodel,用数据驱动页面控件,跟vue中的mvvm渲染数据方式一样,跟微信小程序的MVVM模式一样的,这就实现了界面与数据的分离。

打字不易,截图不易,代码不易,准备不易,原创不易,多多点赞收藏,江湖有你,共同致富。

这篇关于C#上位机与欧姆龙PLC的通信10----开发专用的通讯工具软件(WPF版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/573697

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta