本文主要是介绍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版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!