c#串口通讯wpf的mvvm模式电子称

INotifyPropertyChanged,用来绑定字段

/// <summary>
    /// mvvm的基类
    /// </summary>
    public class NotificationOjbect : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string PropertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
    }

ICommand,用来绑定事件

    /// <summary>
    /// 执行命令
    /// </summary>
    public class DelegateCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        public Action<object> ExecuteAction;
        public Func<object, bool> CanExecuteFunc;

        public DelegateCommand()
        {

        }

        public DelegateCommand(Action<object> execute) : this(execute, null)
        {
        }

        public DelegateCommand(Action<object> execute, Func<object, bool> canExecute)
        {
            if (execute == null)
            {
                return;
            }
            ExecuteAction = execute;
            CanExecuteFunc = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (this.CanExecuteFunc == null)
            {
                return true;
            }
            return this.CanExecuteFunc(parameter);
        }

        public void Execute(object parameter)
        {
            if (this.ExecuteAction != null)
            {
                this.ExecuteAction(parameter);
            }
        }
    }

属性的绑定

 private string _PortName;
        /// <summary>
        /// 端口名称
        /// </summary>
        public string PortName
        {
            get { return _PortName; }
            set
            {
                _PortName = value;
                _notification.RaisePropertyChanged("PortName");
            }
        }

事件的绑定

public ICommand SaveSerialPort
        {
            get
            {
                return new DelegateCommand(
                    (param) =>
                    {
                        btnSave_Click(param);
                    }
                   , (v) => { return true; });
            }
        }

调用代码

this.DataContext = new SerialPortViewModel();

界面绑定属性和事件

 

一个最简单的wpf的mvvm就弄完了

dome的地址:https://gitee.com/cainiaoA/wpfstudent

 串口通讯封装代码

xml序列化,用来报错串口配置

 public class XmlSerializerHelper
    {
        #region Xml系列化
        public static void Serialize<T>(Stream stream, T instance)
        {
            Serialize<T>(stream, instance, null, null, true);
        }

        public static void Serialize<T>(Stream stream, T instance, Encoding encoding)
        {
            Serialize<T>(stream, instance, null, encoding, true);
        }
        public static void Serialize<T>(Stream stream, T instance, XmlSerializerNamespaces ns, bool CloseStream = true)
        {
            if (instance == null) return;
            XmlSerializer xs = new XmlSerializer(typeof(T));
            if (ns == null)
                xs.Serialize(stream, instance);
            else
                xs.Serialize(stream, instance, ns);

            if (CloseStream)
            {
                stream.Close();
            }
        }
        public static void Serialize<T>(Stream stream, T instance, XmlSerializerNamespaces ns, Encoding encoding, bool CloseStream = true)
        {
            if (instance == null) return;
            XmlSerializer xs = new XmlSerializer(typeof(T));

            StreamWriter writer = null;
            if (encoding == null)
                writer = new StreamWriter(stream);
            else
                writer = new StreamWriter(stream, encoding);

            if (ns == null)
                xs.Serialize(writer, instance);
            else
                xs.Serialize(writer, instance, ns);
            if (CloseStream)
            {
                writer.Close();
                stream.Close();
            }
        }
        public static MemoryStream Serialize<T>(T instance)
        {
            return Serialize<T>(instance, null, null);
        }
        public static MemoryStream Serialize<T>(T instance, Encoding encoding)
        {
            return Serialize<T>(instance, null, encoding);
        }
        public static MemoryStream Serialize<T>(T instance, XmlSerializerNamespaces ns)
        {
            if (instance == null) return null;
            MemoryStream ms = new MemoryStream();
            Serialize<T>(ms, instance, ns, false);
            return ms;
        }
        public static MemoryStream Serialize<T>(T instance, XmlSerializerNamespaces ns, Encoding encoding)
        {
            if (instance == null) return null;
            MemoryStream ms = new MemoryStream();
            Serialize<T>(ms, instance, ns, encoding, false);
            return ms;
        }
        public static string SerializeToString<T>(T instance)
        {
            return SerializeToString<T>(instance, null, Encoding.UTF8);
        }
        public static string SerializeToString<T>(T instance, Encoding encoding)
        {
            return SerializeToString<T>(instance, null, encoding);
        }

        public static string SerializeToString<T>(T instance, XmlSerializerNamespaces ns)
        {
            return SerializeToString<T>(instance, ns, Encoding.UTF8);
        }

        public static string SerializeToString<T>(T instance, XmlSerializerNamespaces ns, Encoding encoding)
        {
            using (MemoryStream ms = Serialize(instance, ns, encoding))
            {
                ms.Position = 0;
                using (StreamReader sr = new StreamReader(ms, encoding))
                {
                    return sr.ReadToEnd();
                }
            }
        }

        public static byte[] SerializeToBytes<T>(T instance)
        {
            return SerializeToBytes<T>(instance, null, null);
        }
        public static byte[] SerializeToBytes<T>(T instance, Encoding encoding)
        {
            return SerializeToBytes<T>(instance, null, null);
        }
        public static byte[] SerializeToBytes<T>(T instance, XmlSerializerNamespaces ns)
        {
            using (MemoryStream ms = Serialize<T>(instance, ns))
            {
                return ms.ToArray();
            }
        }
        public static byte[] SerializeToBytes<T>(T instance, XmlSerializerNamespaces ns, Encoding encoding)
        {
            using (MemoryStream ms = Serialize<T>(instance, ns, encoding))
            {
                return ms.ToArray();
            }
        }
        #endregion

        #region xml反系列化

        /// <summary>
        /// XML反系列化
        /// </summary>
        /// <param name="ms">Stream流</param>
        public static T DeSerialize<T>(Stream ms, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            ms.Position = 0;
            using (StreamReader sr = new StreamReader(ms, encoding))
            {
                //通过XmlReader.Create静态方法创建XmlReader实例  
                using (XmlReader rdr = XmlReader.Create(sr))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(T));
                    T model = (T)xs.Deserialize(rdr);
                    return model;
                }
            }
        }

        /// <summary>
        /// XML反系列化
        /// </summary>
        /// <param name="str">xml字符串</param>
        public static T DeSerializeString<T>(string str, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            using (MemoryStream ms = new MemoryStream())
            {
                byte[] bytes = encoding.GetBytes(str);
                BinaryWriter bw = new BinaryWriter(ms);
                bw.Write(bytes);
                return DeSerialize<T>(ms);
            }
        }

        /// <summary>
        /// XML反系列化
        /// </summary>
        /// <param name="bytes">字节数组</param>
        public static T DeSerializeBytes<T>(byte[] bytes, Encoding encoding = null)
        {
            if (encoding == null) encoding = Encoding.UTF8;
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryWriter bw = new BinaryWriter(ms);
                bw.Write(bytes);
                return DeSerialize<T>(ms, encoding);
            }
        }
        #endregion
    }

单例模式,保存串口配置

 public class AppPathAttribute : Attribute
    {
        public AppPathAttribute(string path)
        {
            Path = path;
        }
        public string Path { get; set; }
    }
public class AppBase<T> where T : AppBase<T>
    {

        #region 字段
        private static T _instance;
        private static readonly object _objLock = new object();
        private static FileSystemWatcher m_Watcher;
        /// <summary>
        /// 配置文件完整路径
        /// </summary>
        public static string FullPath { get; private set; }
        #endregion

        #region 构造函数
        static AppBase()
        {
            var type = typeof(T);
            var pathAttr = (AppPathAttribute)type.GetCustomAttributes(typeof(AppPathAttribute), false).FirstOrDefault();
            if (pathAttr != null)
                FullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, pathAttr.Path);
            else
                FullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Config", type.Name + ".config");

            string fileName = Path.GetFileName(FullPath);
            string path = Path.GetDirectoryName(FullPath);
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            m_Watcher = new FileSystemWatcher();
            m_Watcher.Filter = fileName;
            m_Watcher.Path = path;
            m_Watcher.NotifyFilter = NotifyFilters.Attributes |
            NotifyFilters.CreationTime |
            NotifyFilters.DirectoryName |
            NotifyFilters.FileName |
            NotifyFilters.LastAccess |
            NotifyFilters.LastWrite |
            NotifyFilters.Security |
            NotifyFilters.Size;
            m_Watcher.Changed += new FileSystemEventHandler(OnChanged);
            m_Watcher.Created += new FileSystemEventHandler(OnChanged);
            m_Watcher.Deleted += new FileSystemEventHandler(OnChanged);
            m_Watcher.Renamed += new RenamedEventHandler(OnRenamed);
            m_Watcher.EnableRaisingEvents = true;
        }

        private static void OnChanged(object sender, FileSystemEventArgs e)
        {
            lock (_objLock)
            {
                _instance = null;
            }
        }

        private static void OnRenamed(object sender, RenamedEventArgs e)
        {
            lock (_objLock)
            {
                _instance = null;
            }
        }
        #endregion

        #region 属性
        /// <summary>
        ///  单例模式
        /// </summary>
        public static T Instance
        {
            get
            {
                lock (_objLock)
                {
                    if (_instance != null) return _instance;
                    _instance = GetSetting();
                    return _instance;
                }
            }
            set
            {
                lock (_objLock)
                {
                    _instance = value;
                }
            }
        }
        #endregion

        #region 方法
        /// <summary>
        /// 读取本地配置
        /// </summary>
        /// <returns>基类为BaseSetting的对象</returns>
        private static T GetSetting()
        {
            var SettingPath = FullPath;
            if (File.Exists(SettingPath))
            {
                try
                {
                    return WithRetry(() =>
                    {
                        using (var fs = new FileStream(SettingPath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
                        {
                            return XmlSerializerHelper.DeSerialize<T>(fs);
                        }
                    });
                }
                catch (InvalidOperationException) { }
            }
            return Activator.CreateInstance<T>();
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        public void Save()
        {
            m_Watcher.EnableRaisingEvents = false;
            try
            {
                var path = Path.GetDirectoryName(FullPath);
                if (!Directory.Exists(path))
                    Directory.CreateDirectory(path);

                WithRetry(() =>
                {
                    using (var fs = new FileStream(FullPath, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
                    {
                        var ns = new XmlSerializerNamespaces();
                        ns.Add("", "");
                        XmlSerializerHelper.Serialize(fs, _instance, ns);
                    }
                });
            }
            catch
            {
                throw;
            }
            finally
            {
                m_Watcher.EnableRaisingEvents = true;
            }

        }

        private static void WithRetry(Action action, int timeoutMs = 2000)
        {
            var time = Stopwatch.StartNew();
            try
            {
                while (true)
                {
                    try
                    {
                        action();
                        break;
                    }
                    catch (IOException)
                    {
                        if (time.ElapsedMilliseconds < timeoutMs)
                        {
                            throw;
                        }
                    }
                }
            }
            finally
            {
                time.Stop();
            }
        }

        private static Out WithRetry<Out>(Func<Out> action, int timeoutMs = 2000)
        {
            var time = Stopwatch.StartNew();
            try
            {
                while (true)
                {
                    try
                    {
                        return action();
                    }
                    catch (IOException)
                    {
                        if (time.ElapsedMilliseconds > timeoutMs)
                        {
                            throw;
                        }
                    }
                }
            }
            finally
            {
                time.Stop();
            }
        }
        #endregion
    }
#region 委托事件
    /// <summary>
    /// 串口状态
    /// </summary>
    /// <param name="Status"></param>
    public delegate void StatusEvent(bool Status);
    /// <summary>
    /// 数据接收
    /// </summary>
    /// <param name="Data"></param>
    public delegate void DataReceived(string Data);
    /// <summary>
    /// 接收结果委托
    /// </summary>
    /// <param name="StrWeight"></param>
    public delegate void ResultReceived(string StrResult);
    /// <summary>
    /// 接收串口原始委托
    /// </summary>
    /// <param name="OrginData"></param>
    public delegate void OrginDataReceived(string OrginData);
    #endregion

    public class ScalesSerialPort : IDisposable
    {
        #region 参数
        private static readonly SynchronizationContext DefaultSynchronizationContext = new SynchronizationContext();
        private readonly SynchronizationContext _synchronizationContext;

        private static SerialPorter _DefaultSerialPort = new SerialPorter(new SerialPort());
        private SerialPorter _CurrentSerialPort;

        public StatusEvent StatusEvent;
        public OrginDataReceived orginDataReceived;
        public ResultReceived resultReceived;
        #endregion

        #region 构造函数
        public ScalesSerialPort() : this(_DefaultSerialPort)
        {

        }

        public ScalesSerialPort(SerialPort SerialPort) : this(new SerialPorter(SerialPort))
        {

        }

        private ScalesSerialPort(SerialPorter SerialPort)
        {
            _synchronizationContext = SynchronizationContext.Current ?? DefaultSynchronizationContext;
            _CurrentSerialPort = SerialPort;
            _CurrentSerialPort.OrginDataReceived += _serialPort_DataReceived;
            _CurrentSerialPort.resultReceived += _serialPort_ResultReceived;
            _CurrentSerialPort.StatusEvent += _serialPort_StatusEvent;
        }
        #endregion

        #region 初始化
        private void _serialPort_DataReceived(string OrginData)
        {
            _synchronizationContext.Post((arg) =>
            {
                if (orginDataReceived != null)
                    orginDataReceived(OrginData);
            }, null);

        }

        private void _serialPort_ResultReceived(string StrWeight)
        {
            _synchronizationContext.Post((arg) =>
            {
                if (resultReceived != null)
                {
                    resultReceived(StrWeight);
                }
            }, null);
        }

        public void _serialPort_StatusEvent(bool Status)
        {
            _synchronizationContext.Post((arg) =>
            {
                if (StatusEvent != null)
                    StatusEvent(Status);
            }, null);
        }
        #endregion

        #region 方法
        /// <summary>
        /// 串口配置
        /// </summary>
        public void SetConfig(SerialPortSetting setting)
        {
            _CurrentSerialPort.SetConfig(_CurrentSerialPort.SerialPort, setting);
        }
        /// <summary>
        /// 串口状态
        /// </summary>
        public bool IsOpen
        {
            get
            {
                return _CurrentSerialPort.SerialPort.IsOpen;
            }
        }
        /// <summary>
        /// 串口名称
        /// </summary>
        public string PortName
        {
            get { return _CurrentSerialPort.SerialPort.PortName; }
        }
        /// <summary>
        /// 打开串口
        /// </summary>
        public void Open()
        {
            try
            {
                if (!_CurrentSerialPort.SerialPort.IsOpen)
                    _CurrentSerialPort.SerialPort.Open();
            }
            catch
            {
                throw;
            }
            finally
            {

                if (_CurrentSerialPort.StatusEvent != null)
                    _CurrentSerialPort.StatusEvent(_CurrentSerialPort.SerialPort.IsOpen);
            }
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        public void Close()
        {
            try
            {
                _CurrentSerialPort.SerialPort.Close();
            }
            catch
            {
                throw;
            }
            finally
            {
                if (_CurrentSerialPort.StatusEvent != null)
                    _CurrentSerialPort.StatusEvent(_CurrentSerialPort.SerialPort.IsOpen);
            }
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _CurrentSerialPort.OrginDataReceived -= _serialPort_DataReceived;
            _CurrentSerialPort.resultReceived -= _serialPort_ResultReceived;
            _CurrentSerialPort.StatusEvent -= _serialPort_StatusEvent;
        }
        #endregion
    }

    public class SerialPorter
    {
        /// <summary>
        /// 接收数据缓存
        /// </summary>
        private string StrDataReceived = string.Empty;

        private SerialPortSetting _Setting;
        public SerialPortSetting Setting { get { return _Setting; } }
        public SerialPort SerialPort { get; private set; }
        
        public StatusEvent StatusEvent;
        public OrginDataReceived OrginDataReceived;
        public ResultReceived resultReceived;

        public SerialPorter(SerialPort serialPort)
        {
            SerialPort = serialPort;
            SetConfig(serialPort, SerialPortSetting.Instance);
            serialPort.DataReceived += _serialPort_DataReceived;
        }

        public void SetConfig(SerialPort SerialPort, SerialPortSetting setting)
        {
            bool isOpen = SerialPort.IsOpen;
            if (isOpen)
                SerialPort.Close();
            // Allow the user to set the appropriate properties.
            SerialPort.PortName = setting.PortName;// 端口
            SerialPort.BaudRate = setting.BaudRate;//波特率
            SerialPort.Parity = setting.Parity;//奇偶
            SerialPort.DataBits = setting.DataBits;//位数
            SerialPort.StopBits = setting.StopBits;//停止位
                                                   // Set the read/write timeouts
            SerialPort.ReadTimeout = 500;
            SerialPort.WriteTimeout = 500;
            //重新打开串口
            if (isOpen)
                SerialPort.Open();
            _Setting = setting;
        }

        private void _serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            var OrginData = SerialPort.ReadExisting();
            if (OrginDataReceived != null)
                OrginDataReceived(OrginData);

            StrDataReceived += OrginData;
            if (string.IsNullOrWhiteSpace(_Setting.StartChar)) return;
            var lastindex = StrDataReceived.LastIndexOf(_Setting.StartChar);
            if (lastindex <= 0) return;
            var suf = StrDataReceived.Substring(0, lastindex);
            var suflastindex = suf.LastIndexOf(_Setting.StartChar);
            if (suflastindex <= 0) return;
            var WeightData = suf.Substring(suflastindex + 1);
            StrDataReceived = StrDataReceived.Substring(lastindex);

            if (WeightData.Length > 0)
            {
                string StrWeight = string.Empty;
                char[] charArray = WeightData.ToCharArray();
                for (int i = 1; i <= charArray.Length; i++)
                {
                    StrWeight += charArray[charArray.Length - i];
                }
                if (resultReceived != null)
                {
                    resultReceived(StrWeight);
                }
            }

        }
    }

 

posted @ 2020-09-01 10:31  世人皆萌  阅读(609)  评论(0编辑  收藏  举报