MVVM ViewModel实现超级界面端超级解耦
为何要将xaml与xaml.cs两个原本在一起的文件解耦?
超级解耦的主要体现形式为:将界面所有的事件转移到ViewModel中,比如原来界面一个button的click事件,要在界面下面对应的.xaml.cs文件中写相应的事件逻辑,通过超级解耦后,就不需要再在xaml.cs文件中写任何逻辑,一致于可以让这一个文件为创建的时候什么样子,项目做完的时候还是什么样子,一笔都不用谢,这样做的好处就是,原来xaml.cs文件中,如果写了事件,对应的xaml界面文件由于有相应的事件,那么如果没有xaml.cs文件,就无法运行这个项目,就是说xaml与xaml.cs文件严重耦合。而通过超级解耦后,就将两者彻底解耦了。
那么超级解耦有什么好处或者实用性呢?答案就是可以将ViewModel单独抽出一层,可以放在一个独立的类库中,体现上是实现了解耦,更实用的的是通过解耦后可以实现核心代码的高度保密,从而达到一定的商业价值最大化。
姜彦20180522 2118
几个要点
1.使用RelayCommand命令
2.通过nuget添加 Install-Package MvvmLight -Version 5.3.0,用这种方式添加,可以直接派生好相对性的ViewModel、ViewModelLocator.cs,并且直接在App.xaml中自己生成一个资源字典
<ResourceDictionary >
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:AE240_Simulator.ViewModel" />
</ResourceDictionary>
3.在界面的xaml中 增加数据源的绑定 (解决了DataGrid不用在cs代码中,代码绑定的问题)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:View="clr-namespace:Utility.Tool.Controls.View;assembly=Utility.Tool.Controls" xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2" xmlns:View1="clr-namespace:AE240_Simulator.View" x:Class="AE240_Simulator.MainWindow" Title="{Binding Path=SoftVersion}" Height="530" Width="853" WindowStartupLocation="CenterScreen" DataContext="{Binding Main,Source={StaticResource Locator}}" >
实例代码
1.界面
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:View="clr-namespace:Utility.Tool.Controls.View;assembly=Utility.Tool.Controls" xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2" xmlns:View1="clr-namespace:AE240_Simulator.View" x:Class="AE240_Simulator.MainWindow" Title="{Binding Path=SoftVersion}" Height="530" Width="853" WindowStartupLocation="CenterScreen" DataContext="{Binding Main,Source={StaticResource Locator}}" > <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="215" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid Grid.Column="0" > <Grid.RowDefinitions> <RowDefinition Height="220" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Border Grid.Row="0" BorderThickness="1" BorderBrush="#FFB1C1F2" Margin="3,0,0,4" > <Grid Grid.Row="0" > <Label Content="串口号" Height="28" HorizontalAlignment="Left" Margin="5,15,0,0" x:Name="label1" VerticalAlignment="Top" /> <Label Content="数据位" Height="28" HorizontalAlignment="Left" Margin="5,117,0,0" x:Name="label2" VerticalAlignment="Top" /> <Label Content="停止位" Height="28" HorizontalAlignment="Left" Margin="5,83,0,0" x:Name="label3" VerticalAlignment="Top" /> <Label Content="校验位" Height="28" HorizontalAlignment="Left" Margin="5,147,0,0" x:Name="label4" VerticalAlignment="Top" /> <Label Content="流控制" Height="28" HorizontalAlignment="Left" Margin="5,175,0,0" x:Name="label5" VerticalAlignment="Top" /> <Label Content="波特率" Height="28" HorizontalAlignment="Left" Margin="5,49,0,0" x:Name="label6" VerticalAlignment="Top" /> <ComboBox x:Name="cbbPortName" SelectedIndex="0" Height="23" HorizontalAlignment="Left" Margin="50,15,0,0" VerticalAlignment="Top" Width="70" Background="{x:Null}" SelectedItem="{Binding PortName}" ItemsSource="{Binding COMS}" > </ComboBox> <ComboBox x:Name="cbbPortBaudRate" SelectedIndex="12" Height="23" HorizontalAlignment="Left" Margin="50,49,0,0" VerticalAlignment="Top" Width="70" SelectedItem="{Binding BaudRate}" ItemsSource="{Binding Path=BaudRates}" > </ComboBox> <ComboBox x:Name="cbbPortStopBits" SelectedIndex="0" Height="23" HorizontalAlignment="Left" Margin="50,83,0,0" VerticalAlignment="Top" Width="70" ItemsSource="{Binding StopBits}" SelectedItem="{Binding StopBit }" > </ComboBox> <ComboBox x:Name="cbbPortDataBits" SelectedIndex="3" Height="23" HorizontalAlignment="Left" Margin="50,117,0,0" VerticalAlignment="Top" Width="70" ItemsSource="{Binding DataBits}" SelectedItem="{Binding DataBit}" > </ComboBox> <ComboBox x:Name="cbbPortParity" SelectedIndex="0" Height="23" HorizontalAlignment="Left" Margin="50,147,0,0" VerticalAlignment="Top" Width="70" ItemsSource="{Binding Paritys}" SelectedItem="{Binding Parity}" > </ComboBox> <ComboBox x:Name="cbbPortBaseStream" SelectedIndex="0" Height="23" HorizontalAlignment="Left" Margin="50,175,0,0" VerticalAlignment="Top" Width="70" ItemsSource="{Binding BaseStreams}" Text="{Binding BaseStream}" > </ComboBox> <Button Content="打开串口" Height="23" HorizontalAlignment="Left" Margin="130,15,0,0" x:Name="btnOpenPort" VerticalAlignment="Top" Width="75" Background="#00FF99" IsEnabled="{Binding Path=IsOpenPort}" Command="{Binding Path=OpenPort}" CommandParameter="{Binding ElementName=dgFormula}" /> <Button Content="关闭串口" Height="23" HorizontalAlignment="Left" Margin="130,49,0,0" x:Name="btnClosePort" VerticalAlignment="Top" Width="75" Background="#829db2" Command="{Binding Path=ClosePort}" /> <Button Content="解 密" x:Name="btnEncryptViewShow" HorizontalAlignment="Left" Margin="130,84,0,0" VerticalAlignment="Top" Width="75" Command="{Binding Path=EncryptViewShow}" /> <Button Content="LRC校验" x:Name="btnLRCViewShow" HorizontalAlignment="Left" Margin="130,112,0,0" VerticalAlignment="Top" Width="75" Command="{Binding Path=LRCViewShow}" /> <Button Content="Log分析" x:Name="btnLogViewShow" HorizontalAlignment="Left" Margin="130,140,0,0" VerticalAlignment="Top" Width="75" Command="{Binding Path=LogViewShow}" /> </Grid> </Border> <Border Grid.Row="1" BorderThickness="1" BorderBrush="#FFB1C1F2" Margin="3,0,0,4" > <Grid Grid.Row="1" Name="dgControl" > <Grid.Style> <Style TargetType="{x:Type Grid}"> <Style.Triggers> <DataTrigger Binding="{Binding ElementName=cboxControl,Path=IsChecked}" Value="True"> <Setter Property="Visibility" Value="Visible"/> </DataTrigger> <DataTrigger Binding="{Binding ElementName=cboxControl,Path=IsChecked}" Value="False"> <Setter Property="Visibility" Value="Hidden"/> </DataTrigger> </Style.Triggers> </Style> </Grid.Style> <Label Content="IP 地址" Height="28" HorizontalAlignment="Left" Margin="5,15,0,0" x:Name="label8" VerticalAlignment="Top" /> <Label Content="端 口" Height="28" HorizontalAlignment="Left" Margin="5,45,0,0" x:Name="label9" VerticalAlignment="Top" /> <Label Content="WiFi账号" Height="28" HorizontalAlignment="Left" Margin="5,75,0,0" x:Name="label10" VerticalAlignment="Top" /> <Label Content="WiFi密码" Height="28" HorizontalAlignment="Left" Margin="5,105,0,0" x:Name="label11" VerticalAlignment="Top" /> <TextBox x:Name="tboxIP" Height="23" HorizontalAlignment="Left" Margin="65,15,0,0" VerticalAlignment="Top" Width="100" Text="192.168.1.21" /> <TextBox x:Name="tboxPort" Height="23" HorizontalAlignment="Left" Margin="65,45,0,0" VerticalAlignment="Top" Width="100" Text="8080" /> <TextBox x:Name="tboxWiFiName" Height="23" HorizontalAlignment="Left" Margin="65,75,0,0" VerticalAlignment="Top" Width="100" Text="HYBIOME" /> <TextBox x:Name="tboxWiFiPwd" Height="23" HorizontalAlignment="Left" Margin="65,105,0,0" VerticalAlignment="Top" Width="100" Text="1234QWER0" /> <Button Content="测试状态上报" x:Name="btnStartTest" HorizontalAlignment="Left" Margin="125,145,0,0" VerticalAlignment="Top" Width="75" Command="{Binding Path=StartTestCommand}" /> <Button Content="仪器初始化" HorizontalAlignment="Left" Margin="30,145,0,0" VerticalAlignment="Top" Click="Button_Click_2" /> </Grid> </Border> </Grid> <Grid Grid.Column="1" > <Grid.RowDefinitions> <RowDefinition Height="220*" /> <RowDefinition Height="100" /> </Grid.RowDefinitions> <Border Grid.Row="0" BorderThickness="1" BorderBrush="#FFB1C1F2" Margin="3,0,3,4" > <DataGrid Grid.Row="1" x:Name="dgFormula" AutoGenerateColumns="False" SelectionMode="Single" AlternationCount="2" RowHeaderWidth="0" CanUserAddRows="False" VerticalAlignment="Top" RowHeight="25" FontSize="12" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" SelectionUnit="Cell" Style="{StaticResource CommonDataGridStyle}" ColumnHeaderStyle="{StaticResource CommonDataGridColumnHeaderStyle}" ItemsSource="{Binding _FrameContents}" > <DataGrid.Columns> <DataGridTemplateColumn Header="行号" Width="40" > <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid Background="Transparent" Margin="-2"> <TextBox BorderBrush="Transparent" Text="{Binding RowCount, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" HorizontalContentAlignment="Left" Padding="5,0,0,0" VerticalContentAlignment="Center" VerticalAlignment="Stretch" IsReadOnly="True"> <TextBox.Style> <Style TargetType="{x:Type TextBox}"> <Style.Triggers> <DataTrigger Binding="{Binding FrameColor}" Value="True"> <Setter Property="Foreground" Value="Red"/> </DataTrigger> <DataTrigger Binding="{Binding FrameColor}" Value="False"> <Setter Property="Foreground" Value="Green"/> </DataTrigger> </Style.Triggers> </Style> </TextBox.Style> </TextBox> </Grid> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Header="时间" Width="160" > <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid Background="Transparent" Margin="-2"> <TextBox BorderBrush="Transparent" Text="{Binding Time, Mode=TwoWay}" HorizontalContentAlignment="Left" Padding="5,0,0,0" VerticalContentAlignment="Center" VerticalAlignment="Stretch" IsReadOnly="True"> <TextBox.Style> <Style TargetType="{x:Type TextBox}"> <Style.Triggers> <DataTrigger Binding="{Binding FrameColor}" Value="True"> <Setter Property="Foreground" Value="Red"/> </DataTrigger> <DataTrigger Binding="{Binding FrameColor}" Value="False"> <Setter Property="Foreground" Value="Green"/> </DataTrigger> </Style.Triggers> </Style> </TextBox.Style> </TextBox> </Grid> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Header="数据帧" Width="320*" > <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Grid Background="Transparent" Margin="-2"> <TextBox BorderBrush="Transparent" Text="{Binding DataContent, Mode=OneWay, UpdateSourceTrigger=LostFocus}" HorizontalContentAlignment="Left" Padding="5,0,0,0" VerticalContentAlignment="Center" VerticalAlignment="Stretch" IsReadOnly="True"> <TextBox.Style> <Style TargetType="{x:Type TextBox}"> <Style.Triggers> <DataTrigger Binding="{Binding FrameColor}" Value="True"> <Setter Property="Foreground" Value="Red"/> </DataTrigger> <DataTrigger Binding="{Binding FrameColor}" Value="False"> <Setter Property="Foreground" Value="Green"/> </DataTrigger> </Style.Triggers> </Style> </TextBox.Style> </TextBox> </Grid> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> <DataGrid.ContextMenu> <ContextMenu x:Name="dgClear" StaysOpen="True" Background="White" > <MenuItem Header="清空" Command="{Binding Path=DataGridClearCommand}" /> <MenuItem Header="导出" Command="{Binding Path=DataGridExportCommand}" /> <MenuItem Header="发送帧" Name="dgOnlySend" Command="{Binding Path=OnlySendCommand}" /> <MenuItem Header="接收帧" Name="dgOnlyRecv" /> <MenuItem Header="还原" Name="dgOriginal" /> </ContextMenu> </DataGrid.ContextMenu> </DataGrid> </Border> <Grid Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid Grid.Row="0"> <CheckBox Content="16进制接收" Height="16" HorizontalAlignment="Left" Margin="115,6,0,0" x:Name="cboxReMode" VerticalAlignment="Top" IsChecked="{Binding IsRecvHex}" /> <CheckBox Content="16进制发送" Height="16" HorizontalAlignment="Left" Margin="18,6,0,0" x:Name="cboxSendMode" VerticalAlignment="Top" IsChecked="{Binding IsSendHex}" /> <CheckBox Content="发送新行" Height="16" Margin="452,6,101,0" x:Name="cboxSendNewLine" VerticalAlignment="Top" Visibility="Hidden" /> <CheckBox x:Name="cboxCount" Content="{Binding Path=RecvCount, Mode=TwoWay}" IsChecked="{Binding Path=IsRecvCount, Mode=TwoWay}" HorizontalAlignment="Left" Margin="275,5,0,0" VerticalAlignment="Top" Width="100" Command="{Binding Path=RecvCountClearCommand}" /> <CheckBox x:Name="cboxIsReply" Content="自动回复" HorizontalAlignment="Left" Margin="202,5,0,0" VerticalAlignment="Top" IsChecked="{Binding IsReply}" /> <CheckBox x:Name="cboxControl" Content="功能" HorizontalAlignment="Right" Margin="0,5,5,0" VerticalAlignment="Top" IsChecked="{Binding IsControl}" /> </Grid> <Border Grid.Row="1" BorderThickness="1" BorderBrush="#FFB1C1F2" Margin="3,0,3,4" > <Grid Grid.Row="1"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="200" /> </Grid.ColumnDefinitions> <Grid Grid.Column="0"> <Label Content="发送数据:" Height="28" Margin="14,14,0,0" x:Name="label7" VerticalAlignment="Top" HorizontalAlignment="Left" Width="70" /> <TextBox x:Name="tboxSendStr" Height="23" Margin="78,15,14,0" VerticalAlignment="Top" Text="{Binding SendFrame, Mode=TwoWay}" > <TextBox.ContextMenu> <ContextMenu x:Name="cmClearSend" StaysOpen="true" Background="White" > <MenuItem Header="清空" Command="{Binding Path=SendFrameClearCommand}" /> </ContextMenu> </TextBox.ContextMenu> </TextBox> </Grid> <Grid Grid.Column="1"> <Button Content="发送" Height="23" HorizontalAlignment="Left" Margin="6,14,0,0" x:Name="btnSend" VerticalAlignment="Top" Width="75" Command="{Binding Path=SendCommand}" /> <CheckBox x:Name="cbxCmdType" Content="新命令" HorizontalAlignment="Left" Margin="10,42,0,0" VerticalAlignment="Top" Visibility="Hidden" /> <Button x:Name="btnDebug" Content="Debug" HorizontalAlignment="Left" Margin="101,14,0,0" VerticalAlignment="Top" Command="{Binding Path=DebugViewShow}" /> </Grid> </Grid> </Border> </Grid> </Grid> <Grid x:Name="girdLoading" Background="Transparent" Margin="200,0,200,20" Height="0" VerticalAlignment="Center"> <Popup x:Name="popLoading" PopupAnimation="Fade" PlacementTarget="{Binding ElementName=girdLoading}" Placement="Center" AllowsTransparency="True" StaysOpen="False" IsOpen="False"/> </Grid> </Grid> </Window>
2.xaml.cs
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using System; using System.Collections.Generic; using System.Linq; using System.Text; 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.Navigation; using System.Windows.Shapes; //using Utility.Tool.Model; using Utility.Tool.Controller; using System.IO.Ports; using System.Threading; using System.Collections; using System.Windows.Threading; using System.Collections.ObjectModel; using AE240_Simulator.Model; using System.ComponentModel; using AE240_Simulator.View; using System.Diagnostics; using AE240_Simulator.Controller; using AE240_Simulator.ViewModel; namespace AE240_Simulator { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click_2(object sender, RoutedEventArgs e) { //SplashWindow splashView = new SplashWindow(); //splashView.Show(); //ThreadPool.QueueUserWorkItem(state => //{ // //放置耗时的操作 姜彦20180504 1126 // Thread.Sleep(5 * 1000); // this.Dispatcher.BeginInvoke(new Action(() => // { // splashView.Close(); // })); //}); ////DataGridView dgView = new DataGridView(); ////dgView.Show(); // string str= System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); try { //double i = 0; //double j = 1; ////i = 1 / (j-1); //int[] array = new int[3]; //array[3] = 4; //TryTest(); } catch (Exception ex) { //throw(ex); throw new Exception("",ex); } } #region try catch 测试 private void TryTest() { try { double i = 0; double j = 1; //i = 1 / (j-1); int[] array = new int[3]; array[3] = 4; } catch (Exception ex) { //throw (ex); throw new Exception("",ex); } } #endregion } }
3.ViewModel
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using AE240_Simulator.Controller; using AE240_Simulator.Model; using AE240_Simulator.View; using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.IO.Ports; using System.Text; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; namespace AE240_Simulator.ViewModel { /// <summary> /// This class contains properties that the main View can data bind to. /// <para> /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel. /// </para> /// <para> /// You can also use Blend to data bind with the tool's support. /// </para> /// <para> /// See http://www.galasoft.ch/mvvm /// </para> /// </summary> public class MainViewModel : ViewModelBase { /// <summary> /// Initializes a new instance of the MainViewModel class. /// </summary> public MainViewModel() { ////if (IsInDesignMode) ////{ //// // Code runs in Blend --> create design time data. ////} ////else ////{ //// // Code runs "for real" ////} Initealize(); BuildCommand(); //this._FrameContents = new ObservableCollection<FrameContent>();//ObservableCollection this._FrameContentsCopy = new ObservableCollection<FrameContent>(); this._FrameContentsFilter = new ObservableCollection<FrameContent>(); } #region 属性 #region 控件绑定属性 private string _SendFrame; /// <summary> /// 发送帧 /// </summary> public string SendFrame { get { return _SendFrame; } set { if (_SendFrame!=value) { _SendFrame = value; RaisePropertyChanged("SendFrame"); // RaisePropertyChanged(() => _SendFrame);//这种方式的前提是 里面的必须是一个属性 而不是字段 姜彦20180519 1717 oyear } } } private bool? _IsRecvCount = true; /// <summary> /// 是否开启计数 /// </summary> public bool? IsRecvCount { get { return _IsRecvCount; } set { _IsRecvCount = value; RaisePropertyChanged("IsRecvCount"); } } private string _RecvCount="计数:"; /// <summary> /// 接收帧计数 /// </summary> public string RecvCount { //get { return "计数:" + _iCount.ToString(); } get { return _RecvCount; } set { _RecvCount = value; RaisePropertyChanged("RecvCount"); } } /// <summary> /// 是否是十六进制接收模式 /// </summary> public bool IsRecvHex { get { return _IsRecvHex; } set { _IsRecvHex = value; RaisePropertyChanged("IsRecvHex"); } } /// <summary> /// 是否是十六进制发送模式 /// </summary> public bool IsSendHex { get { return _IsSendHex; } set { _IsSendHex = value; RaisePropertyChanged("IsSendHex"); } } /// <summary> /// 是否主动回复 /// </summary> public bool IsReply { get { return _IsReply; } set { _IsReply = value; RaisePropertyChanged("IsReply"); } } /// <summary> /// 软件标题 /// </summary> public string SoftVersion { get { return "AE240下位机模拟器 "+GetVersion(); } } private bool _IsControl = true; /// <summary> /// 是否打开控制面板 /// </summary> public bool IsControl { get { return _IsControl; } set { _IsControl = value; RaisePropertyChanged("IsControl"); } } private bool _IsOpenPort = true; /// <summary> /// 是否打开了串口 /// </summary> public bool IsOpenPort { get { return _IsOpenPort; } set { _IsOpenPort = value; RaisePropertyChanged("IsOpenPort"); } } #region 串口信息 #region 下拉框 /// <summary> /// 串口列表 /// </summary> public List<string> COMS { get; set; } /// <summary> /// 波特率列表 /// </summary> public List<string> BaudRates { get; set; } /// <summary> /// 停止位列表 /// </summary> public List<string> StopBits { get; set; } /// <summary> /// 数据位列表 /// </summary> public List<string> DataBits { get; set; } /// <summary> /// 校验位列表 /// </summary> public List<string> Paritys { get; set; } /// <summary> /// 流控制列表 /// </summary> public List<string> BaseStreams { get; set; } #endregion /// <summary> /// 串口名称 /// </summary> public string PortName { get { return _PortInfo.PortName; } set { _PortInfo.PortName = value; RaisePropertyChanged("PortName"); } } /// <summary> /// 波特率 /// </summary> public int BaudRate { get { return _PortInfo.BaudRate; } set { _PortInfo.BaudRate = value; RaisePropertyChanged("BaudRate"); } } /// <summary> /// 奇偶校验位 /// </summary> public Parity Parity { get { return _PortInfo.Parity; } set { _PortInfo.Parity = value; RaisePropertyChanged("Parity"); } } /// <summary> /// 数据位 /// </summary> public int DataBit { get { return _PortInfo.DataBit; } set { _PortInfo.DataBit = value; RaisePropertyChanged("DataBit"); } } /// <summary> /// 停止位 /// </summary> public StopBits StopBit { get { return _PortInfo.StopBit; } set { _PortInfo.StopBit = value; RaisePropertyChanged("StopBit"); } } /// <summary> /// 流控制 /// </summary> public Stream BaseStream { get { return _PortInfo.BaseStream; } set { _PortInfo.BaseStream = value; RaisePropertyChanged("BaseStream"); } } #endregion #endregion #region 公共属性 /// <summary> /// 计数:接收帧计数 /// </summary> private int _iCount = 0; /// <summary> /// 串口信息 /// </summary> TSerialPortModel _PortInfo = new TSerialPortModel(); /// <summary> /// 控制串口类 实例化对象 /// </summary> TSerialPortController _PortCon; private ObservableCollection<FrameContent> frameslists = new ObservableCollection<FrameContent>(); /// <summary> /// DataGrid表格绑定对象集合 /// </summary> public ObservableCollection<FrameContent> _FrameContents { get { return frameslists; } set { frameslists = value; RaisePropertyChanged("_FrameContents"); } } /// <summary> /// DataGrid表格绑定对象集合-副本 /// </summary> public ObservableCollection<FrameContent> _FrameContentsCopy; /// <summary> /// 是否是十六进制接收模式 /// </summary> private bool _IsRecvHex = true; /// <summary> /// 是否是十六进制发送模式 /// </summary> private bool _IsSendHex = true; /// <summary> /// 是否主动回复 /// </summary> private bool _IsReply = true; /// <summary> /// 软件版本号 /// </summary> public string _Version = "AE240下位机"; /// <summary> /// 行号 /// </summary> private int _RowCount = 1; /// <summary> /// 筛选过后的行号 /// </summary> private int _RowCountFilter = 1; /// <summary> /// DataGrid表格绑定对象集合-筛选后的 /// </summary> public ObservableCollection<FrameContent> _FrameContentsFilter; /// <summary> /// 指令调度者 /// </summary> private DispatchInvoke _FrameInvoker = new DispatchInvoke(); /// <summary> /// 一个未赋值的DataGrid 等待传参进来后赋值 以实现滚动条自动滚动 姜彦20180522 2004 /// </summary> private DataGrid _DataGridMain = new DataGrid(); #endregion #endregion #region RelayCommand 控件传递命令 /// <summary> /// Log分析窗口显示 /// </summary> public RelayCommand LogViewShow { get; set; } /// <summary> /// LRC校验窗口显示 /// </summary> public RelayCommand LRCViewShow { get; set; } /// <summary> /// 字节窗口显示 /// </summary> public RelayCommand EncryptViewShow { get; set; } /// <summary> /// Debug窗口显示 /// </summary> public RelayCommand DebugViewShow { get; set; } /// <summary> /// 打开串口 /// </summary> public RelayCommand<DataGrid> OpenPort { get; set; } /// <summary> /// 关闭串口 /// </summary> public RelayCommand ClosePort { get; set; } /// <summary> /// 发送 /// </summary> public RelayCommand SendCommand { get; set; } /// <summary> /// 清空表格内容 /// </summary> public RelayCommand DataGridClearCommand { get; set; } /// <summary> /// 导出表格内容 /// </summary> public RelayCommand DataGridExportCommand { get; set; } /// <summary> /// 接收帧计数清零 /// </summary> public RelayCommand RecvCountClearCommand { get; set; } /// <summary> /// 开始测试 /// </summary> public RelayCommand StartTestCommand { get; set; } /// <summary> /// 只显示发送帧 /// </summary> public RelayCommand OnlySendCommand { get; set; } #endregion #region 方法 #region 执行命令 private void BuildCommand() { LogViewShow = new RelayCommand(ExecuteLogViewShow); LRCViewShow = new RelayCommand(ExecuteLRCViewShow); EncryptViewShow = new RelayCommand(ExecuteEncryptViewShow); DebugViewShow = new RelayCommand(ExecuteDebugViewShow); OpenPort = new RelayCommand<DataGrid>(ExecuteOpenPort); ClosePort = new RelayCommand(ExecuteClosePort); SendCommand = new RelayCommand(ExecuteSendCommand); DataGridClearCommand = new RelayCommand(ExecuteDataGridClearCommand); DataGridExportCommand = new RelayCommand(ExecuteDataGridExportCommand); RecvCountClearCommand = new RelayCommand(new Action(()=> { _iCount = 0;RecvCount = "计数:"; }));//里面的()=>_iCount = 0 是自己想出来的 太棒了 姜彦20180519 2326 StartTestCommand = new RelayCommand(ExecuteStartTestCommand); OnlySendCommand = new RelayCommand(ExecuteOnlySendCommand); } /// <summary> /// 分析Log /// </summary> private void ExecuteLogViewShow() { LogView logView = new LogView(); logView.Show(); } /// <summary> /// 计算LRC校验值 /// </summary> private void ExecuteLRCViewShow() { LRCView lRCView = new LRCView(); lRCView.Show(); } /// <summary> /// 字节加密 /// </summary> private void ExecuteEncryptViewShow() { EncryptView encryptView = new EncryptView(); encryptView.Show(); } /// <summary> /// Debug 组帧界面 /// </summary> private void ExecuteDebugViewShow() { DebugView debugView = new DebugView(); debugView.Show(); debugView.OnDataGeted += (sendFrameModel) => { string sendStr = sendFrameModel.ToString(); SendFrame = sendStr; }; //View 退出事件 姜彦20170306 debugView.OnClosed += (Flag) => { debugView.Close(); }; } private void ExecuteOpenPort(DataGrid dg) { IsOpenPort = false; _PortInfo.PortName = PortName; _PortInfo.BaudRate = BaudRate;// Convert.ToInt32(cbbPortBaudRate.Text); _PortInfo.DataBit = DataBit;//Convert.ToInt32(cbbPortDataBits.Text); _PortInfo.StopBit = StopBit;// (StopBits)Convert.ToDouble(cbbPortStopBits.Text);//设置当前停止位 SelectedValue _PortCon = new TSerialPortController(_PortInfo); _PortCon.Open(); /*雷公版本需注释*/ _PortCon.Received += DataRoute;//姜彦 20180205 // portCon.OnReceived +=DataRoute2;//以上两种写法都可以 姜彦20180317 2126 //portCon.OnReceived += new Action<byte[]>(DataRoute2); //Eleven老师那学习到的观察者模式 非常精炼有用 20180316 0020 _PortCon.ComRec(); // btnOpenPort.IsEnabled = false; AddListener(); _DataGridMain = dg; } private void ExecuteClosePort() { _PortCon.Close(); // btnOpenPort.IsEnabled = true; RemoveListener(); IsOpenPort = true; } private void ExecuteSendCommand() { SendStr(SendFrame); } private void ExecuteDataGridClearCommand() { this._FrameContents.Clear(); this._FrameContentsFilter.Clear(); this._RowCount = 1; //this.dgFormula.ItemsSource = this._FrameContents; } private void ExecuteDataGridExportCommand() { List<FrameContent> frameContentList = new List<FrameContent>(); foreach (FrameContent frame in _FrameContents) { frameContentList.Add(frame); } System.Windows.Forms.FolderBrowserDialog folderDlg = new System.Windows.Forms.FolderBrowserDialog(); System.Windows.Forms.DialogResult dialogResult = folderDlg.ShowDialog(); if (dialogResult == System.Windows.Forms.DialogResult.Cancel) { return; } string excelPath = folderDlg.SelectedPath + @"\"; excelPath += "AE240数据帧记录" + DateTime.Now.ToString("yyyyMMddHHmmss"); excelPath += @".xls"; bool result = ExcelHelper.ExportExport(excelPath, frameContentList); if (result == true) { MessageBox.Show("导出数据成功!"); } else { MessageBox.Show("导出数据!", "", MessageBoxButton.OK, MessageBoxImage.Warning); } } private void ExecuteStartTestCommand() { TestStart(); } private void ExecuteOnlySendCommand() { this._FrameContentsFilter.Clear(); this._RowCountFilter = 1; foreach (FrameContent frame in this._FrameContents) { FrameContent frameNew = frame; if (frameNew.FrameColor == false) { frameNew.RowCount = _RowCountFilter; _RowCountFilter++; this._FrameContentsFilter.Add(frameNew); } } //this._FrameContentsCopy.Clear(); //this._FrameContentsCopy = this._FrameContents; //this._FrameContents.Clear(); //this._FrameContents = this._FrameContentsFilter; } private void ExecuteOnlyRecvCommand() { this._FrameContentsFilter.Clear(); this._RowCountFilter = 1; foreach (FrameContent frame in this._FrameContents) { FrameContent frameNew = frame; if (frameNew.FrameColor == true) { frameNew.RowCount = _RowCountFilter; _RowCountFilter++; this._FrameContentsFilter.Add(frameNew); } } // this.dgFormula.ItemsSource = this._FrameContentsFilter; } #region 原来测试DataGrid 滚动条自动下拉 代码 第一个方法成功 自己想出来的 非常有成就感 public void ExecuteScrollBarToEnd(DataGrid dg) { // dg.ScrollIntoView(dg.Items.Count - 1); //dg.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], dg.Columns[0]); _DataGridMain = dg; } public void ExecuteSelectionChanged(object sender, SelectionChangedEventArgs e) { //((DataGrid)sender).SelectedIndex = ((DataGrid)sender).Items.Count - 1; ((DataGrid)sender).ScrollIntoView(_FrameContents[_FrameContents.Count - 1], ((DataGrid)sender).Columns[0]); } public void ExecuteSelectionChanged0(object sender) { //((DataGrid)sender).SelectedIndex = ((DataGrid)sender).Items.Count - 1; ((DataGrid)sender).ScrollIntoView(_FrameContents[_FrameContents.Count - 1], ((DataGrid)sender).Columns[0]); } #endregion #endregion #region 方法 #region 延时方法 /// <summary> /// 延时:ms /// </summary> /// <param name="ms"></param> public void Delay(int ms) { int tick = Environment.TickCount; while (Environment.TickCount - tick < ms) { DoEvent(); } } /// <summary> /// 模仿C#的Application.Doevent函数。可以适当添加try catch 模块 /// </summary> public void DoEvent() { DispatcherFrame frame = new DispatcherFrame(); Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame); Dispatcher.PushFrame(frame); } public object ExitFrame(object f) { ((DispatcherFrame)f).Continue = false; return null; } //*********************************************** #endregion #region 获取版本 Version /// 获取当前系统的版本号 /// </summary> /// <returns></returns> private string GetVersion() { return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); } #endregion #region 事件的委托方法 /// <summary> /// 开启监听 /// </summary> private void AddListener() { _FrameInvoker.OnAllStandbyed += AllStandby; _FrameInvoker.OnCleanRTed += CleanRT; } /// <summary> /// 停止监听 /// </summary> private void RemoveListener() { _FrameInvoker.OnAllStandbyed -= AllStandby; _FrameInvoker.OnCleanRTed -= CleanRT; } /// <summary> /// 开始分析 /// </summary> private void AnalyzeStart() { AllStandby(); CleanRT(); } /// <summary> /// 仪器初始化 /// </summary> private void AllStandby() { List<string> standybyList = new List<string> { "FA F0 31 00 04 00 03 0A 00 00 00 00 00 00 40 00 00 00 7A 45 7F 30 10 01 0A 00 00 00 00 00 00 00 00 05 FB", "FA F0 31 00 06 00 03 0A 00 00 00 00 00 01 00 00 00 00 7A 45 7F 30 10 02 0A 00 00 00 00 00 00 00 00 41 FB", "FA F0 31 00 08 00 03 0A 00 00 00 00 00 01 40 00 00 00 7A 45 7F 30 10 03 0A 00 00 00 00 00 00 00 00 7E FB", "FA F0 31 00 09 00 03 0A 00 00 00 00 00 02 00 00 00 00 7A 45 7F 30 10 04 0A 00 00 00 00 00 00 00 00 3B FB", "FA F0 31 00 0D 00 03 0A 00 00 00 00 00 02 40 00 00 00 7A 45 7F 30 10 05 0A 00 00 00 00 00 00 00 00 76 FB", "FA F0 31 00 0F 00 03 0A 00 00 00 00 00 03 00 00 00 00 7A 45 7F 30 10 06 0A 00 00 00 00 00 00 00 00 32 FB", "FA F0 31 00 10 00 03 0A 00 00 00 00 00 03 40 00 00 00 7A 45 7F 30 10 07 0A 00 00 00 00 00 00 00 00 70 FB", "FA F0 31 00 14 00 03 0A 00 00 00 00 00 04 00 00 00 00 7A 45 7F 30 10 08 0A 00 00 00 00 00 00 00 00 2A FB", "FA F0 31 00 16 00 03 0A 00 00 00 00 00 04 40 00 00 00 7A 45 7F 30 10 09 0A 00 00 00 00 00 00 00 00 67 FB", "FA F0 31 00 17 00 03 0A 00 00 00 00 00 05 00 00 00 00 7A 45 7F 30 10 0A 0A 00 00 00 00 00 00 00 00 24 FB", "FA F0 32 00 18 00 03 0A 00 00 00 00 00 05 40 00 00 00 7A 45 7F 30 10 00 0A 0A 00 00 00 00 00 00 00 62 FB", }; SendList(standybyList); } /// <summary> /// 清理反应杯 /// </summary> private void CleanRT() { List<string> cleanRTList = new List<string> { "FA F0 31 00 1A 00 03 06 00 00 00 00 00 00 40 00 00 00 5E 46 1F 30 10 01 06 00 3C 00 1E 18 FB", "FA F0 31 00 1A 00 03 06 00 00 00 00 00 00 40 00 00 00 5E 46 1F 30 10 02 06 00 3C 00 1E 17 FB", "FA F0 31 00 1B 00 03 06 00 00 00 00 00 01 00 00 00 00 5E 46 1F 30 10 03 06 00 3C 00 1E 54 FB", "FA F0 31 00 1D 00 03 06 00 00 00 00 00 01 40 00 00 00 5E 46 1F 30 10 04 06 00 3C 00 1E 11 FB", "FA F0 31 00 1F 00 03 06 00 00 00 00 00 02 00 00 00 00 5E 46 1F 30 10 05 06 00 3C 00 1E 4D FB", "FA F0 31 00 20 00 03 06 00 00 00 00 00 02 40 00 00 00 5E 46 1F 30 10 06 06 00 3C 00 1E 0B FB", "FA F0 31 00 23 00 03 06 00 00 00 00 00 03 40 00 00 00 5E 46 1F 30 10 00 06 01 3C 00 1E 0C FB", "FA F0 31 00 24 00 03 06 00 00 00 00 00 04 00 00 00 00 5E 46 1F 30 10 00 06 09 3C 00 1E 42 FB", "FA F0 31 00 2E 00 03 06 00 00 00 00 00 07 40 00 00 00 5E 46 1F 30 10 00 06 00 3C 03 1E 7B FB", "FA F0 31 00 2F 00 03 06 00 00 00 00 00 08 00 00 00 00 5E 46 1F 30 10 00 06 00 3C 10 1E 2C FB", "FA F0 32 00 30 00 03 09 00 00 00 00 00 08 40 00 00 00 5E 46 1F 30 10 00 06 06 00 3C 3C 00 1E 1E 17 FB", }; SendList(cleanRTList); } /// <summary> /// 开始一个测试 /// </summary> private void TestStart() { List<string> cleanRTList = new List<string> { "FA F1 13 00 25 00 02 07 00 00 00 00 00 00 40 00 00 00 01 04 04 41 41 30 34 1F FB ", "FA F1 14 00 26 00 02 0F 00 00 00 00 00 00 40 00 00 00 04 01 01 01 0A 73 70 6F 32 2D 33 6F 70 2A 2B 5B FB", "FA F1 2B 00 2A 00 03 00 00 00 00 00 00 00 40 00 00 00 00 40 00 00 00 37 FB", "FA F1 22 00 2B 00 04 01 00 00 00 00 00 00 40 00 00 00 2E 15 60 00 00 00 40 00 00 00 01 19 FB", "FA F1 2C 00 2C 00 04 04 00 00 00 00 00 00 40 00 00 00 2E 15 60 00 00 01 00 00 00 00 00 00 01 01 49 FB", "FA F1 24 00 2D 00 05 03 00 00 00 00 00 00 40 00 00 00 2E 15 60 00 00 10 01 00 00 00 00 00 00 00 00 01 03 01 3D FB", "FA F1 24 00 2F 00 05 03 00 00 00 00 00 01 00 00 00 00 2E 15 60 00 00 71 08 40 00 00 00 00 00 00 00 00 01 01 55 FB", "FA F1 24 00 EF 00 05 03 00 00 00 00 00 25 40 00 00 00 2E 15 60 00 00 74 00 60 00 00 00 00 00 00 00 03 03 01 11 FB", "FA F1 24 00 F0 00 05 03 00 00 00 00 00 26 00 00 00 00 2E 15 60 00 00 59 01 00 00 00 00 00 00 00 00 02 17 01 36 FB", "FA F1 25 00 35 00 05 00 00 00 00 00 00 00 40 00 00 00 2E 15 60 00 00 1F 00 00 00 00 1E 00 20 00 00 70 FB", }; SendList(cleanRTList); } #endregion /// <summary> /// 初始化 /// </summary> private void Initealize() { COMS = new List<string>(); GetPorts(); LoadViewInfo(); //port = new TSerialPortController(portInfo); //SerialPortInitealize(); //SendString = "绑定测试"; } /// <summary> /// 加载界面信息 /// </summary> private void LoadViewInfo() { BaudRates = new List<string>(); BaudRates.Add("110"); BaudRates.Add("300"); BaudRates.Add("600"); BaudRates.Add("1200"); BaudRates.Add("2400"); BaudRates.Add("4800"); BaudRates.Add("9600"); BaudRates.Add("14400"); BaudRates.Add("19200"); BaudRates.Add("38400"); BaudRates.Add("56000"); BaudRates.Add("57600"); BaudRates.Add("115200"); DataBits = new List<string>(); DataBits.Add("5"); DataBits.Add("6"); DataBits.Add("7"); DataBits.Add("8"); StopBits = new List<string>(); StopBits.Add("1"); StopBits.Add("1.5"); StopBits.Add("2"); Paritys = new List<string>(); Paritys.Add("NONE"); Paritys.Add("ODD"); Paritys.Add("EVEN"); Paritys.Add("MARK"); Paritys.Add("SPACE"); BaseStreams = new List<string>(); BaseStreams.Add("NONE"); } /// <summary> /// 获取机器串口list /// </summary> public void GetPorts() { string[] slist = TSerialPortController.GetPorts(); foreach (string name in slist) { COMS.Add(name); } } /// <summary> /// 数据路由 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void DataRoute(object sender, TSerialPortController.ReceivedEventArgs e) { if (e != null) { _iCount++; if ((bool)IsRecvCount) { RecvCount = "计数:" + _iCount.ToString(); } string recData = string.Empty; byte[] recBuffer = e._ReceBuffer; if (_IsRecvHex) { StringBuilder recBuffer16 = new StringBuilder();//定义16进制接收缓存 for (int i = 0; i < recBuffer.Length; i++) { recBuffer16.AppendFormat("{0:X2}" + " ", recBuffer[i]);//X2表示十六进制格式(大写),域宽2位,不足的左边填0。 } recData = recBuffer16.ToString(); } else { IsReply = false; string rechar = string.Empty; rechar = System.Text.Encoding.Default.GetString(recBuffer);//转码 recData = rechar; } FrameContent frame = new FrameContent(); frame.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); frame.DataContent = "发送帧:" + recData;// e._ReceiveData; frame.FrameColor = false; ////DataGridTextBoxShow(frame);// goto 表格控件逐行显示 ////_FrameContents.Add(frame); //Action<FrameContent> action=new Action<FrameContent>(_FrameContents.Add); //action.BeginInvoke(frame,null,null); frame.RowCount = _RowCount; _RowCount++; ThreadPool.QueueUserWorkItem(delegate { System.Threading.SynchronizationContext.SetSynchronizationContext(new System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher)); System.Threading.SynchronizationContext.Current.Post(pl => { //里面写真正的业务内容 _FrameContents.Add(frame);//重要技术点 姜彦20180519 1939 _DataGridMain.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], _DataGridMain.Columns[0]); }, null); }); try { if (_IsReply) { //if (cbxCmdType.IsChecked!=true) //{ string strSend = string.Empty; byte[] datas = new byte[11]; /*姜彦 20180413 1926 注释*/ //TSendFrameEntity sendFrameEntity = new TSendFrameEntity(e._RecvFrameEntity); //datas = sendFrameEntity.ToData();//扩展方法在这里使用 大大简化了转化过程 简化了代码 姜彦20180209 // datas[(int)SebufferPosition.FRAME_LRC] = TPacketParserController.CalculateLRC(datas.Skip(1).Take(6).ToList()); /*姜彦 20180413 1926 注释*/ /*新的发送帧Model 姜彦20180414 1927*/ SendFrameModel sendFrameModel = new SendFrameModel(e._ReceBuffer); datas = sendFrameModel.ToByte(); if (sendFrameModel.IsReply == 0x00 && sendFrameModel.CmdID != CommandID.MSG_PARAMETERREPORT) { return; } for (int i = 0; i < datas.Length; i++) { strSend = strSend + " " + Convert.ToString(datas[i], 16).PadLeft(2, '0'); } TSendDataModel sendStr = new TSendDataModel() { SendSetData = strSend, SendSetMode = true, IsNewLine = false, }; Send(sendStr); _FrameInvoker.FrameDispatcher(e); } //} //_FrameInvoker.FrameDispatcher(e); } catch(Exception ex) { throw new Exception("",ex); } } } /// <summary> /// 发送数据 /// </summary> /// <param name="sendStr"></param> void Send(TSendDataModel sendStr) { _PortCon.Send(sendStr); _PortCon.ReceiveStaus = true; FrameContent frame = new FrameContent(); frame.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); frame.DataContent = ("接收帧:" + sendStr.SendSetData).Replace("\r\n", ""); frame.FrameColor = true; // DataGridTextBoxShow(frame);//goto frame.RowCount = _RowCount; _RowCount++; ThreadPool.QueueUserWorkItem(delegate { System.Threading.SynchronizationContext.SetSynchronizationContext(new System.Windows.Threading.DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher)); System.Threading.SynchronizationContext.Current.Post(pl => { //里面写真正的业务内容 _FrameContents.Add(frame);//重要技术点 姜彦20180519 1939 _DataGridMain.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], _DataGridMain.Columns[0]); }, null); }); } /// <summary> /// 发送字符串数据 /// </summary> /// <param name="Str"></param> void SendStr(string Str) { TSendDataModel sendStr = new TSendDataModel(); sendStr.SendSetData = Str; sendStr.SendSetMode = _IsSendHex; sendStr.IsNewLine = false; _PortCon.Send(sendStr); FrameContent frame = new FrameContent(); frame.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); frame.DataContent = ("接受帧:" + sendStr.SendSetData).Replace("\r\n", ""); frame.FrameColor = true; // DataGridTextBoxShow(frame);//goto frame.RowCount = _RowCount; _RowCount++; ThreadPool.QueueUserWorkItem(delegate { SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher)); SynchronizationContext.Current.Post(pl => { //里面写真正的业务内容 _FrameContents.Add(frame);//重要技术点 姜彦20180519 1939 _DataGridMain.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], _DataGridMain.Columns[0]); }, null); }); } /// <summary> /// 发送字符串List /// </summary> /// <param name="sendList"></param> void SendList(List<string> sendList) { TSendDataModel sendStr = new TSendDataModel(); foreach (string standyby in sendList) { Delay(1000); sendStr.SendSetData = standyby; //sendStr.SendSetMode = cboxSendMode.IsChecked; //sendStr.IsNewLine = cboxSendNewLine.IsChecked; //Dispatcher.BeginInvoke(new Action(delegate //{ // //https://www.cnblogs.com/DemonJ/p/6265989.html // /* // * BeginInvoke()异步执行,不等待委托结束就更新, // * Invoke()同步执行,需等待委托执行完。 // */ // //你的操作。。。 // //如:textBox.Text = ""; // sendStr.SendSetMode = cboxSendMode.IsChecked; // sendStr.IsNewLine = cboxSendNewLine.IsChecked; //})); sendStr.SendSetMode = _IsSendHex; sendStr.IsNewLine = false; _PortCon.Send(sendStr); FrameContent frame = new FrameContent(); frame.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); frame.DataContent = ("接受帧:" + sendStr.SendSetData).Replace("\r\n", ""); frame.FrameColor = true; //DataGridTextBoxShow(frame);//goto frame.RowCount = _RowCount; _RowCount++; ThreadPool.QueueUserWorkItem(delegate { SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher)); SynchronizationContext.Current.Post(pl => { //里面写真正的业务内容 _FrameContents.Add(frame);//重要技术点 姜彦20180519 1939 _DataGridMain.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], _DataGridMain.Columns[0]); }, null); }); } } #endregion #endregion } }
4.ViewModelLocator.cs 这个文件是nuget添加MVVM的时候,自动生成的
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* In App.xaml: <Application.Resources> <vm:ViewModelLocator xmlns:vm="clr-namespace:AE240_Simulator" x:Key="Locator" /> </Application.Resources> In the View: DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}" You can also use Blend to do all this with the tool's support. See http://www.galasoft.ch/mvvm */ using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Ioc; using Microsoft.Practices.ServiceLocation; namespace AE240_Simulator.ViewModel { /// <summary> /// This class contains static references to all the view models in the /// application and provides an entry point for the bindings. /// </summary> public class ViewModelLocator { /// <summary> /// Initializes a new instance of the ViewModelLocator class. /// </summary> public ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); ////if (ViewModelBase.IsInDesignModeStatic) ////{ //// // Create design time view services and models //// SimpleIoc.Default.Register<IDataService, DesignDataService>(); ////} ////else ////{ //// // Create run time view services and models //// SimpleIoc.Default.Register<IDataService, DataService>(); ////} SimpleIoc.Default.Register<MainViewModel>(); } public MainViewModel Main { get { return ServiceLocator.Current.GetInstance<MainViewModel>(); } } public static void Cleanup() { // TODO Clear the ViewModels } } }
![](https://files-cdn.cnblogs.com/files/jiangyan219/Alipay.bmp)
您的资助是我最大的动力!
金额随意,欢迎来赏!
![](https://files-cdn.cnblogs.com/files/jiangyan219/WeChat.bmp)
我写的东西能让你能懂,那是义务
毕竟占用了你生命中的宝贵的时间和注意力
要是你还能喜欢我的作品,那就是缘分了
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的因为,我的写作热情也离不开您的肯定支持,感谢您的阅读,我是【青青子衿】!