1.最常用的一种方式,写在xaml.cs文件中的代码 姜彦20180522 2137
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#region DataGrid 跨线程委托输出显示方法 姜彦20180315 1439 /// <summary> /// DataGrid控件直接接受串口返回数据委托 /// </summary> /// <param name="e"></param> public delegate void DataGridReceiverDelegate(TSerialPortController.ReceivedEventArgs e); public void DataGridReceiver(TSerialPortController.ReceivedEventArgs e) { FrameContent frameData = new FrameContent(); frameData.Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); frameData.DataContent = e._ReceiveData; _FrameContents.Add(frameData); } public void DataGridReceiverShow(TSerialPortController.ReceivedEventArgs e) { this.dgFormula.Dispatcher.Invoke(new DataGridReceiverDelegate(DataGridReceiver), e); } /// <summary> /// DataGrid控件输出FrameContent对象委托 /// </summary> /// <param name="frameContent"></param> public delegate void DataGridTextBoxShowDelegate(FrameContent frameContent); public void DataGridTextBox(FrameContent frameContent) { _FrameContents.Add(frameContent); dgFormula.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], dgFormula.Columns[0]);//滚动条自动跟踪 姜彦20180315 1929 } /// <summary> /// 将数据显示到DataGrid表格中 /// </summary> /// <param name="frameContent"></param> public void DataGridTextBoxShow(FrameContent frameContent) { frameContent.RowCount = _RowCount; _RowCount++; this.dgFormula.Dispatcher.BeginInvoke(new DataGridTextBoxShowDelegate(DataGridTextBox), frameContent); }
2.当通过ViewModel超级解耦后,又该怎么实现呢?
思路就是,通过上面的代码我们不难发现,实现自动滚动的主要的要点就是在dg.ScrollIntoView() 这个方法中,而通过超级解耦后,ViewModel中其实是不存在任何真实的界面控件的,否则就无法超级解耦,那么dg.ScrollIntoView()显然无法摆脱控件,怎么办呢?
首先通过任何一个Command 传一个CommandParameter到ViewModel里,传的这个参数就是DataGrid,具体的实现方式为
<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}" />
然后就是,在ViewModel中添加一个DataGrid的类型的全局变量,通过RelayCommand命令将界面上的DataGrid传递进来
/// <summary> /// 一个未赋值的DataGrid 等待传参进来后赋值 以实现滚动条自动滚动 姜彦20180522 2004 /// </summary> private DataGrid _DataGridMain = new DataGrid(); /// <summary> /// 打开串口 /// </summary> public RelayCommand<DataGrid> OpenPort { get; set; } 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; } OpenPort = new RelayCommand<DataGrid>(ExecuteOpenPort);
最后,就是在_FrameContents.Add的地方 ,套用一下_DataGridMain.ScrollIntoView(_FrameContents[_FrameContents.Count - 1], _DataGridMain.Columns[0]); 即可