上节开发了一个winform版的通讯测试工具,这节再搞个wpf版的,wpf是什么?请自行百度,也可以看前面的博客,WPF真入门教程,wpf的界面效果是比winform漂亮,因为wpf使用了web项目中的css样式来美化界面,在这个例子中用到wpf的控件,资源样式,命令绑定等,采用的是mvvm的渲染模式,界面如图:
前面的winform界面:
MsgBoxWindow.xaml代码
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
{
///
/// MsgBoxWindow.xaml 的交互逻辑
///
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;
}
///
/// 显示按钮类型
///
public enum CustomMessageBoxButton
{
OK = 1,
OKCancel = 2,
YesNo = 3,
YesNoCancel = 4
}
///
/// 消息框返回值
///
public enum CustomMessageBoxResult
{
None = 0,//用户直接关闭消息框
OK = 1,//用户点击了确定按钮
Cancel = 2,//用户点击了取消按钮
Yes = 3,//用户点击了是按钮
No = 4//用户点击了否按钮
}
///
/// 图标类型
///
public enum CustomMessageBoxIcon
{
None = 0,
Error = 1,
Question = 2,
Infomation = 3
}
#region 页面属性定义
///
/// 消息文本
///
public string MessageBoxText { get; set; }
///
/// 消息框标题
///
public string MessageTitle { get; set; }
///
/// 图标路径
///
public string ImagePath { get; set; }
///
/// 显示确定
///
public Visibility OkButtonVisibility { get; set; }
///
/// 显示取消
///
public Visibility CancelButtonVisibility { get; set; }
///
/// 显示是
///
public Visibility YesButtonVisibility { get; set; }
///
/// 显示否
///
public Visibility NoButtonVisibility { get; set; }
///
/// 消息框返回值
///
public CustomMessageBoxResult Result { get; set; }
#endregion
private 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();
}
///
/// 消息框拖动
///
///
///
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
///
/// 显示消息框
///
///
///
///
///
///
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;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace OmronFinsWPFApp.Common
{
///
/// 命令实现类
///
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged;
///
/// 要执行的操作
///
private Action
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
{
///
/// 视图模型基类
///
public class ViewModelBase : INotifyPropertyChanged
{
///
/// 属性值发生更改时触发
///
public event PropertyChangedEventHandler PropertyChanged;
///
/// 执行更改
/// C#5.0中的新特性CallerMemberName
///
///
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
///
/// 成功消息提示
///
///
///
///
public void ShowMessage(string message, string title = "提示", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK)
{
Show(message, title, buttons, CustomMessageBoxIcon.Infomation);
}
///
/// 错误消息框
///
///
///
///
public void ShowError(string message, string title = "错误", CustomMessageBoxButton buttons = CustomMessageBoxButton.OK)
{
Show(message, title, buttons, CustomMessageBoxIcon.Error);
}
///
/// 询问消息框
///
///
///
///
///
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
{
///
/// 视图模型
///
public class MainViewModel : ViewModelBase
{
///
/// finstcp对象
///
FinsTcp finsTcp;
PLCMemoryModel readPLCModel = SetInitModel();
///
/// 读取PLC
///
public PLCMemoryModel ReadPLCModel
{
get { return readPLCModel; }
set
{
readPLCModel = ReadPLCModel;
OnPropertyChanged();//属性通知
}
}
PLCMemoryModel writePLCModel = SetInitModel();
///
/// 写入PLC
///
public PLCMemoryModel WritePLCModel
{
get { return writePLCModel; }
set
{
writePLCModel = WritePLCModel;
OnPropertyChanged();
}
}
///
/// 初始化页面参数
///
///
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";
///
/// PLC地址
///
public string HostName
{
get
{
return hostName;
}
set
{
hostName = value;
}
}
private string hostPort = "7788";
///
/// PLC端口
///
public string HostPort
{
get { return hostPort; }
set
{
hostPort = value;
}
}
///
/// 存储区下拉框数据源
///
public List CboCustTypes
{
get
{
return new List() { "DM", "H", "W", "CIO" };
}
}
///
/// 数据类型
///
public List CboCustDatas
{
get
{
return new List() { "ushort", "short", "float", "bool" };
}
}
private string readWords = "";
///
/// 读数结果
///
public string ReadWords
{
get { return readWords; }
set
{
readWords = value;
OnPropertyChanged();
}
}
private string writeWords = "";
///
/// 写入数据
///
public string WriteWords
{
get { return writeWords; }
set
{
writeWords = value;
OnPropertyChanged();
}
}
private string connectWords = "当前未连接";
///
/// 连接状态
///
public string ConnectWords
{
get { return connectWords; }
set
{
connectWords = value;
OnPropertyChanged();
}
}
///
///
/// 登录按钮的命令处理
///
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();// 开始连接PLC
if (!result.IsSuccessed)
{
ShowError(result.Message, "错误");
return;
}
ShowMessage("PLC连接成功", "提示");
ConnectWords = "PLC连接成功";
});
}
}
///
///
/// 读取按钮的命令处理
///
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(plcAddr, readCount);
if (!datas.IsSuccessed)
{
ShowMessage(datas.Message, "提示");
return;
}
ReadWords = string.Join(",", datas.Datas);
break;
case "short":
var datas2 = finsTcp.Read(plcAddr, readCount);
if (!datas2.IsSuccessed)
{
ShowMessage(datas2.Message, "提示");
return;
}
ReadWords = string.Join(",", datas2.Datas);
break;
case "float":
var datas3 = finsTcp.Read(plcAddr, readCount);
if (!datas3.IsSuccessed)
{
ShowMessage(datas3.Message, "提示");
return;
}
ReadWords = string.Join(",", datas3.Datas);
break;
case "bool":
var datas4 = finsTcp.Read(plcAddr, readCount);
if (!datas4.IsSuccessed)
{
ShowMessage(datas4.Message, "提示");
return;
}
ReadWords = string.Join(",", datas4.Datas);
break;
}
});
}
}
///
///
/// 写入按钮的命令处理
///
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 vals = objWriteVals.Split(',').ToList();
switch (dataType)
{
case "ushort":
//实际数值转换成list集合ushort类型
List objushort = new List();
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 objshort = new List();
vals.ForEach((x) =>
{
objshort.Add(short.Parse(x));
});
var finish2 = finsTcp.Write(objshort, plcAddr);
if (finish2.IsSuccessed)
{
ShowMessage(finish2.Message, "提示");
}
break;
case "float":
//实际数值转换成list集合 float
List objfloat = new List();
vals.ForEach((x) =>
{
objfloat.Add(float.Parse(x));
});
var finish3 = finsTcp.Write(objfloat, plcAddr);
if (finish3.IsSuccessed)
{
ShowMessage(finish3.Message, "提示");
}
break;
case "bool":
//实际数值转换成list集合bool
List objbool = new List();
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;
}
});
}
}
}
}
首先添加资源文件
使用资源文件
运行起来效果
全部通讯报文
本例子用到WPF的MVVM模式,不是winform中的按钮点击事件,是后台绑定viewmodel,用数据驱动页面控件,跟vue中的mvvm渲染数据方式一样,跟微信小程序的MVVM模式一样的,这就实现了界面与数据的分离。
打字不易,截图不易,代码不易,准备不易,原创不易,多多点赞收藏,江湖有你,共同致富。