<file_sep>﻿using CardWorkbench.Models;
using DevExpress.Mvvm;
using DevExpress.Mvvm.UI;
using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.Editors;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.LayoutControl;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace CardWorkbench.ViewModels.CommonTools
{
    public class FrameDumpViewModel : ViewModelBase
    {
        //Button名称
        public readonly string BUTTON_PLAY_FRAMEDATA_NAME = "startFrameData_btn";
        public readonly string BUTTON_RECORD_FRAMEDATA_NAME = "recordFrameData_btn";
        //Button Image控件名称
        public readonly string IMAGE_PLAY_FRAMEDATA_NAME = "playFrameDataImg";
        public readonly string IMAGE_RECORD_FRAMEDATA_NAME = "recordFrameDataImg";
        //Image资源路径
        public readonly string PATH_IMAGE_PLAY_PAUSE = "/Images/play/pause.png";
        public readonly string PATH_IMAGE_PLAY_PLAY = "/Images/play/play.png";
        public readonly string PATH_IMAGE_PLAY_RECORD = "/Images/play/record.png";
        public readonly string PATH_IMAGE_PLAY_RECORDING = "/Images/play/recording.png";

        //按钮提示文本
        public readonly string TOOLTIP_BUTTON_PLAY_FRAMEDATA = "开始";
        public readonly string TOOLTIP_BUTTON_PAUSE_FRAMEDATA = "暂停";
        public readonly string TOOLTIP_BUTTON_RECORD_FRAMEDATA = "记录";
        public readonly string TOOLTIP_BUTTON_STOP_RECORD_FRAMEDATA = "停止记录";

        //FRAMEData的Grid名称
        public readonly string GRID_FRAMEDATA_NAME = "frameGrid";
        //显示"当前时间"的textbox名称
        public readonly string TEXTBOX_CURRENTTIME_NAME = "currentTimeTextbox";
        //模式切换下拉框名称
        public readonly string COMBOBOX_CHANGEMODEL_NAME = "modeChangeComboBox";
        //模式切换下拉选项名称
        public readonly string COMBOBOX_CHANGEMODEL_REALTIME = "实时";
        public readonly string COMBOBOX_CHANGEMODEL_PLAYBACK = "回放";
        //回放设置组名称
        public readonly string LAYOUTGROUP_PLAYBACK_NAME = "playBack_setting_group";
        //回放时间显示panel名称
        public readonly string PANEL_RECORDTIME_NAME = "recordTimePanel";
        //回放时间显示image名称
        public readonly string IMAGE_RECORDTIME_NAME = "recordTimeImage";
        //回放时间显示文本名称
        public readonly string TEXTBLOCK_RECORDTIME_NAME = "recordTimeText";
        
        private DispatcherTimer record_timer = null;    //记录数据时的timer
        private DateTime startTime; //记录数据时的起始时间
        private TimeSpan timePassed, timeSinceLastStop; //记录间隔时间，自上次记录停止的间隔时间(暂时没用到)
        private TextBlock recordTimeText; //记录时间显示文本

        private DispatcherTimer timer = new DispatcherTimer();  //模拟grid数据刷新的timer
        GridControl frameDataGrid = null;
        int frameNum = 9;  //临时子帧号
        int fullFrameCount = 0;  //已接收的全帧个数
        int updateRowCount = 0; //更新的行
        int filterTempRow = 0;  //筛选后的更新行
        bool isTimerPause = false;  //刷新计时器是否暂停
        string filterFrameID = "ALL";  //筛选子帧ID的临时变量
        bool isReset = false; //是否重置接收数据

        //获得文件选择对话框服务
        public IOpenFileDialogService OpenFileDialogService { get { return GetService<IOpenFileDialogService>(); } }

        //获得保存文件对话框服务
        public ISaveFileDialogService SaveFileDialogService { get { return GetService<ISaveFileDialogService>(); } }  

        /// <summary>
        /// 原始帧显示模块打开加载后执行命令
        /// </summary>
        public ICommand frameDumpLoadedCommand {
            get { return new DelegateCommand<RoutedEventArgs>(onframeDumpLoaded, x => { return true; }); }
        }

        private void onframeDumpLoaded(RoutedEventArgs e)
        {
           
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);

            StackPanel recordTimeTextPanel = LayoutHelper.FindElementByName(root, PANEL_RECORDTIME_NAME) as StackPanel;

            TextBox currentTimeTextbox = recordTimeTextPanel.FindName(TEXTBOX_CURRENTTIME_NAME) as TextBox;
            DispatcherTimer _timer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1), DispatcherPriority.Normal, delegate
            {
                currentTimeTextbox.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            }, currentTimeTextbox.Dispatcher);
        }

        /// <summary>
        /// 点击“开始”接收或播放数据命令
        /// </summary>
        public ICommand startFrameDataCommand
        {
            get { return new DelegateCommand<RoutedEventArgs>(onStartFrameDataClick, x => { return true; }); }
        }

        private void onStartFrameDataClick(RoutedEventArgs e)
        {
            //获得必要的界面对象
            ToggleButton startFrameData_btn = e.Source as ToggleButton;
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(startFrameData_btn as DependencyObject);
            ToggleButton recordFrameDataButton = LayoutHelper.FindElementByName(root, BUTTON_RECORD_FRAMEDATA_NAME) as ToggleButton;
            Image playFrameDataImg = startFrameData_btn.FindName(IMAGE_PLAY_FRAMEDATA_NAME) as Image;
            Image recordFrameDataImg = recordFrameDataButton.FindName(IMAGE_RECORD_FRAMEDATA_NAME) as Image;
            Image recordFlashImage = LayoutHelper.FindElementByName(root, IMAGE_RECORDTIME_NAME) as Image;
            StackPanel recordTimeTextPanel = LayoutHelper.FindElementByName(root, PANEL_RECORDTIME_NAME) as StackPanel;
            ComboBoxEdit comboBox = LayoutHelper.FindElementByName(root, COMBOBOX_CHANGEMODEL_NAME) as ComboBoxEdit;
            string modeComboBoxValue = comboBox.EditValue as string;
            frameDataGrid = (GridControl)LayoutHelper.FindElementByName(root, GRID_FRAMEDATA_NAME);

            if (startFrameData_btn.IsChecked == true)   //开始播放
            {
                //更改按钮外观
                playFrameDataImg.Source = new BitmapImage(new Uri(PATH_IMAGE_PLAY_PAUSE, UriKind.Relative));
                startFrameData_btn.ToolTip = TOOLTIP_BUTTON_PAUSE_FRAMEDATA;
                //当前模式是实时时记录按钮可点击
                if (COMBOBOX_CHANGEMODEL_REALTIME.Equals(modeComboBoxValue))
                {
                    recordFrameDataButton.IsEnabled = true;
                }

                //新建一个线程去更新datagrid
                //List<FrameModel> row_lst = frameDataGrid.ItemsSource as List<FrameModel>;
                //foreach (FrameModel rowModel in row_lst)
                //{
                //    UpdateFrameGridWorker thread_worker = new UpdateFrameGridWorker(rowModel);
                //    Thread workerThread = new Thread(thread_worker.DoWork);
                //    workerThread.Start();
                //    thread_worker.DoWork();
                //}
                timer.Interval = TimeSpan.FromMilliseconds(500);
                if (!isTimerPause)
                {
                    timer.Tick += new EventHandler(doWork);
                }
                timer.Start();
                
            }
            else   //暂停播放
            {
                //还原按钮外观
                playFrameDataImg.Source = new BitmapImage(new Uri(PATH_IMAGE_PLAY_PLAY, UriKind.Relative));
                startFrameData_btn.ToolTip = TOOLTIP_BUTTON_PLAY_FRAMEDATA;

                //如果正在记录则需停止记录
                if (recordFrameDataButton.IsChecked == true)
                {
                    stopRecordFrameData(recordFrameDataButton, recordFrameDataImg, recordFlashImage, recordTimeTextPanel);
                }
                recordFrameDataButton.IsEnabled = false; //记录按钮不可用
     
                //控制刷新计时器
                timer.Stop();
                isTimerPause = true; //暂停刷新
            }

        }

        /// <summary>
        /// "记录"数据按钮命令
        /// </summary>
        public ICommand recordFrameDataCommand
        {
            get { return new DelegateCommand<RoutedEventArgs>(onRecordFrameDataClick, x => { return true; }); }
        }

        private void onRecordFrameDataClick(RoutedEventArgs e)
        {
            ToggleButton recordFrameData_btn = e.Source as ToggleButton;
            Image recordFrameDataImg = recordFrameData_btn.FindName(IMAGE_RECORD_FRAMEDATA_NAME) as Image;
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(recordFrameData_btn as DependencyObject);
            StackPanel recordTimeTextPanel = LayoutHelper.FindElementByName(root, PANEL_RECORDTIME_NAME) as StackPanel;
            Image recordFlashImage = recordTimeTextPanel.FindName(IMAGE_RECORDTIME_NAME) as Image;
            recordTimeText = recordTimeTextPanel.FindName(TEXTBLOCK_RECORDTIME_NAME) as TextBlock;
            
            if (recordFrameData_btn.IsChecked == true)  //开始记录
            {
                //TODO 需要判断 1.当前是否有支持记录的设备 2.当前是否开始已开始运行实时数据

                //更改按钮外观
                recordFrameDataImg.Source = new BitmapImage(new Uri(PATH_IMAGE_PLAY_RECORDING, UriKind.Relative));
                recordFrameData_btn.ToolTip = TOOLTIP_BUTTON_STOP_RECORD_FRAMEDATA;
                //显示记录时间，开始动画
                recordTimeTextPanel.Visibility = Visibility.Visible;
                DoubleAnimation da = new DoubleAnimation();
                da.From = 1;
                da.To = 0.2;
                da.RepeatBehavior = RepeatBehavior.Forever;
                da.AutoReverse = true;
                da.Duration = TimeSpan.FromMilliseconds(500);
                recordFlashImage.BeginAnimation(TextBlock.OpacityProperty, da);

                //开始记录，启动记录时间文本的定时器
                record_timer = new DispatcherTimer();
                record_timer.Tick += record_timer_tick;
                record_timer.Interval = new TimeSpan(0, 0, 0, 0, 1);
                startTime = DateTime.Now;
                record_timer.Start();
            }
            else
            {
                //停止记录
                stopRecordFrameData(recordFrameData_btn, recordFrameDataImg, recordFlashImage, recordTimeTextPanel);
                //恢复记录按钮状态
                recordFrameData_btn.IsEnabled = true;
            }

        }

        /// <summary>
        /// 设置时间文本的handle函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void record_timer_tick(object sender, object e) {
            timePassed = DateTime.Now - startTime;
            recordTimeText.Text = convertNumberString((timeSinceLastStop + timePassed).Hours) + ":"
                                + convertNumberString((timeSinceLastStop + timePassed).Minutes) + ":"
                                + convertNumberString((timeSinceLastStop + timePassed).Seconds) + "."
                                + convertNumberString((timeSinceLastStop + timePassed).Milliseconds);
        }

        /// <summary>
        /// 时间值（时分秒）文本转换，转换数字为两位数文本
        /// </summary>
        /// <param name="number">时分秒数值</param>
        /// <returns>时分秒文本</returns>
        private string convertNumberString(int number) {
            string result;
            if (number < 10)
            {
                result = "0" + number;
                return result;
            }
            result = number.ToString();
            return result;
        }

        /// <summary>
        /// 停止记录数据
        /// </summary>
        /// <param name="recordFrameDataButton">记录数据按钮对象</param>
        /// <param name="recordFrameDataImg">记录数据按钮图标</param>
        /// <param name="recordFlashImage">记录数据时显示的图片</param>
        /// <param name="recordTimeTextPanel">记录数据时显示的panel</param>
        private void stopRecordFrameData(ToggleButton recordFrameDataButton, Image recordFrameDataImg, Image recordFlashImage, StackPanel recordTimeTextPanel)
        {
            //停止记录计时
            if (record_timer != null)
            {
                record_timer.Stop();
                record_timer = null;
            }
            else
            {
                return; //当前没有记录数据则退出
            }
            //重置记录按钮状态  
            recordFrameDataButton.IsChecked = false;
            //还原按钮外观
            recordFrameDataImg.Source = new BitmapImage(new Uri(PATH_IMAGE_PLAY_RECORD, UriKind.Relative));
            recordFrameDataButton.ToolTip = TOOLTIP_BUTTON_RECORD_FRAMEDATA;
            //弹出记录文件“另存为...”对话框
            SaveFileDialogService.Filter = "数据文件|*.dat"; ;
            SaveFileDialogService.FilterIndex = 1;
            bool saveResult = SaveFileDialogService.ShowDialog();
            if (saveResult)
            {
                //TODO 写入数据文件
                MessageBox.Show("保存成功");
            }
            //结束动画，隐藏记录时间
            recordFlashImage.BeginAnimation(TextBlock.OpacityProperty, null);
            recordTimeTextPanel.Visibility = Visibility.Hidden;

        }

        private void doWork(object sender, EventArgs e)
        {
            List<FrameModel> row_lst = frameDataGrid.ItemsSource as List<FrameModel>;
            //开始更新datagrid
           // foreach (FrameModel rowModel in row_lst.OrderBy(rowModel => rowModel.FrameID))

            frameDataGrid.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (frameNum % row_lst.Count == 1 )  //翻页
	            {
		            updateRowCount = 0; //还原成更新第一行
                    isReset = false; //还原重置标记
                    fullFrameCount += 1;  //接收到全帧数递增1
                }
                if (isReset)
                {
                    updateRowCount = 0; //还原成更新第一行
                    isReset = false; //还原重置标记
                }

                if ("ALL".Equals(this.filterFrameID))
                {
                    int ID = updateRowCount+1;
                    row_lst[updateRowCount] = new FrameModel() { FrameID = frameNum, SyncWord = "EB101", Word1 = "FF"+frameNum, Word2 = "FFF", Word3 = "FF"+frameNum, ID = ID + "", Word5 = "FFFF", Word6 = "FFFF", Word7 = "FFFF", Word8 = "FFFF", Word9 = "FFFF", Word10 = "FFFF", Word11 = "FFFF", Word12 = "FFFF" };
                    frameDataGrid.RefreshRow(updateRowCount);
                }
                else
                {
                    int result = int.Parse(this.filterFrameID);
                    //Console.WriteLine("result:" + result);
                    //Console.WriteLine("frameNum:" + frameNum);
                    //Console.WriteLine("fullFrameCount:" + fullFrameCount);

                    if (frameNum == result || frameNum == result + row_lst.Count * fullFrameCount)  //所有是过滤值的才更新
                    {
                        if (filterTempRow % row_lst.Count == 0)
                        {
                            filterTempRow = 0;
                        }
                        //Console.WriteLine("update row:"+updateRowCount);
                        row_lst[filterTempRow] = new FrameModel() { FrameID = frameNum, SyncWord = "EB101", Word1 = "FF" + frameNum, Word2 = "FFF", Word3 = "FF" + frameNum, ID = result + "", Word5 = "FFFF", Word6 = "FFFF", Word7 = "FFFF", Word8 = "FFFF", Word9 = "FFFF", Word10 = "FFFF", Word11 = "FFFF", Word12 = "FFFF" };
                        frameDataGrid.RefreshRow(filterTempRow);
                        filterTempRow++;
                    }
                }
                updateRowCount++;
                frameNum++;
                
            }));
        }

        /// <summary>
        /// 过滤子帧号命令
        /// </summary>
        public ICommand filterFrameIDCommand {
            get { return new DelegateCommand<RoutedEventArgs>(onfilterFrameIDChanged, x => { return true; }); }
        }

        private void onfilterFrameIDChanged(RoutedEventArgs e) {
            ComboBoxEdit comboBox = e.Source as ComboBoxEdit;
            string filterId = comboBox.EditValue as string;
            filterFrameID = filterId;
            isReset = true;
        }

        /// <summary>
        /// 设置当前模式命令
        /// </summary>
        public ICommand changeModelCommand
        {
            get { return new DelegateCommand<RoutedEventArgs>(onChangeModel, x => { return true; }); }
        }

        private void onChangeModel(RoutedEventArgs e)
        {
            //TODO 1. 如有数据，则先停止暂停当前的数据播放

            //2.切换模式
            ComboBoxEdit comboBox = e.Source as ComboBoxEdit;
            string model = comboBox.EditValue as string;
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(comboBox as DependencyObject);
            LayoutGroup playBackSettingGroup = LayoutHelper.FindElementByName(root, LAYOUTGROUP_PLAYBACK_NAME) as LayoutGroup;
            ToggleButton recordFrameDataBtn = LayoutHelper.FindElementByName(root, BUTTON_RECORD_FRAMEDATA_NAME) as ToggleButton;
            ToggleButton startFrameData_btn = LayoutHelper.FindElementByName(root, BUTTON_PLAY_FRAMEDATA_NAME) as ToggleButton;
            Image playFrameDataImg = startFrameData_btn.FindName(IMAGE_PLAY_FRAMEDATA_NAME) as Image;
            Image recordFrameDataImg = recordFrameDataBtn.FindName(IMAGE_RECORD_FRAMEDATA_NAME) as Image;
            Image recordFlashImage = LayoutHelper.FindElementByName(root, IMAGE_RECORDTIME_NAME) as Image;
            StackPanel recordTimeTextPanel = LayoutHelper.FindElementByName(root, PANEL_RECORDTIME_NAME) as StackPanel;

            if (COMBOBOX_CHANGEMODEL_REALTIME.Equals(model))  //实时模式
            {
                //回放设置不可见
                playBackSettingGroup.IsEnabled = false;
                playBackSettingGroup.IsCollapsed = true;
               
            }
            else if (COMBOBOX_CHANGEMODEL_PLAYBACK.Equals(model)) //回放模式
            {
                //回放设置可见
                playBackSettingGroup.IsEnabled = true;
                playBackSettingGroup.IsCollapsed = false;
            }
            //暂停接收数据,如当前正在记录则弹出保存对话框
            pauseReceiveFrameData(startFrameData_btn, recordFrameDataBtn, playFrameDataImg, recordFrameDataImg,recordFlashImage, recordTimeTextPanel);
            //还原“播放”按钮状态
            startFrameData_btn.IsChecked = false;
        }

        /// <summary>
        /// 暂停接收数据,更改按钮状态。如当前正在记录则弹出保存对话框
        /// </summary>
        /// <param name="startFrameData_btn">播放数据按钮对象</param>
        /// <param name="recordFrameDataButton">记录数据按钮对象</param>
        /// <param name="playFrameDataImg">播放数据按钮图标</param>
        /// <param name="recordFrameDataImg">记录数据按钮图标</param>
        /// <param name="recordFlashImage">记录时间文本图标</param>
        /// <param name="recordTimeTextPanel">记录时间panel</param>
        private void pauseReceiveFrameData(ToggleButton startFrameData_btn, ToggleButton recordFrameDataButton, Image playFrameDataImg, Image recordFrameDataImg, Image recordFlashImage, StackPanel recordTimeTextPanel)
        {
            //如果正在接收数据，还原“播放”按钮状态和外观
            if (startFrameData_btn.IsChecked == true)
            {
                //还原“播放”按钮状态和外观
                playFrameDataImg.Source = new BitmapImage(new Uri(PATH_IMAGE_PLAY_PLAY, UriKind.Relative));
                startFrameData_btn.ToolTip = TOOLTIP_BUTTON_PLAY_FRAMEDATA;

                //TODO 暂停播放数据
                
                //----临时停止刷新计时器----
                    timer.Stop();
                    isTimerPause = true; //暂停刷新
                //-----
            }
            //如果正在记录数据，提示另存为，隐藏记录时间文本
            if (recordFrameDataButton.IsChecked == true)
            {
                stopRecordFrameData(recordFrameDataButton, recordFrameDataImg, recordFlashImage, recordTimeTextPanel);
            }
            recordFrameDataButton.IsEnabled = false; //重置记录按钮状态        

        }

        /// <summary>
        /// 选择回放文件按钮命令
        /// </summary>
        public ICommand selectPlayBackDatafileCommand
        {
            get { return new DelegateCommand<RoutedEventArgs>(onSelectPlayBackDatafile, x => { return true; }); }
        }
        private void onSelectPlayBackDatafile(RoutedEventArgs e)
        {
            Button buttonInfo = e.Source as Button;
            ButtonEdit be = LayoutHelper.FindLayoutOrVisualParentObject<ButtonEdit>(buttonInfo as DependencyObject);
            if (be == null)
                return;
            //System.Windows.Forms.FileDialog dialog = new System.Windows.Forms.OpenFileDialog();
            //if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            //{
            //    be.EditValue = dialog.FileName;
            //}
            OpenFileDialogService.Filter = "数据文件|*.dat";
            OpenFileDialogService.FilterIndex = 1;
            bool DialogResult = OpenFileDialogService.ShowDialog();
            if (DialogResult)
            {
               IFileInfo file = OpenFileDialogService.Files.First();
               be.EditValue = file.Name;
            }
            
        }

    }

    //子线程刷新
    //public class UpdateFrameGridWorker
    //{
    //    List<FrameModel> row_lst;
    //    GridControl frameDataGrid;
    //    public UpdateFrameGridWorker(List<FrameModel> row_lst, GridControl frameDataGrid)
    //    {
    //        this.row_lst = row_lst;
    //        this.frameDataGrid = frameDataGrid;
    //    }

    //    public void DoWork()
    //    {
    //        //开始更新datagrid
    //       // foreach (FrameModel rowModel in row_lst.OrderBy(rowModel => rowModel.FrameID))
    //        frameDataGrid.Dispatcher.BeginInvoke(new Action(() =>
    //        {
    //            for (int i = 0; i < row_lst.Count; i++)
    //            {
    //                row_lst[i] = new FrameModel() { FrameID = 9, SyncWord = "EB101", Word1 = "FFFF", Word2 = "FFF", Word3 = "FFFF", ID = 9 + "", Word5 = "FFFF", Word6 = "FFFF", Word7 = "FFFF", Word8 = "FFFF", Word9 = "FFFF", Word10 = "FFFF", Word11 = "FFFF", Word12 = "FFFF" };
    //                frameDataGrid.RefreshRow(i);
    //            }
    //        }));
    //            //row.ItemArray = new object[] { 9, "EB101", "FFFF", "FFFF", "FFFF", 9 + "", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF", "FFFF" };
    //    }
    //    public void RequestStop()
    //    {
    //        _shouldStop = true;
    //    }
    //    // Volatile is used as hint to the compiler that this data
    //    // member will be accessed by multiple threads.
    //    private volatile bool _shouldStop;
    //}

    //事件发生前转换类
    //public class StartFrameDataBtnClickEventArgsConverter : EventArgsConverterBase<RoutedEventArgs>
    //{
    //    //按钮文本常量
    //    public readonly string BUTTON_CONTENT_START = "开始"; 
    //    public readonly string BUTTON_CONTENT_STOP = "停止";


    //    protected override object Convert(RoutedEventArgs args)
    //    {
    //        GridControl frameDataGrid = null;
    //        ToggleButton startFrameData_btn = args.Source as ToggleButton;

    //        FrameworkElement root = LayoutHelper.GetTopLevelVisual(startFrameData_btn as DependencyObject);
    //        frameDataGrid = (GridControl)LayoutHelper.FindElementByName(root, "frameGrid");

    //        if (startFrameData_btn.IsChecked == true)
    //        {
    //            startFrameData_btn.Content = BUTTON_CONTENT_STOP;
    //            //frameDataGrid.ItemsSource = FrameTestCase.generateData();
    //        }
    //        else {
    //            startFrameData_btn.Content = BUTTON_CONTENT_START;
    //        }

    //        return frameDataGrid;
    //    }
    //}
}
<file_sep>﻿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 CardWorkbench.Views.CommonTools;
using CardWorkbench.Views.CommonControls;
using CardWorkbench.Views.MenuControls;
using DevExpress.Xpf.NavBar;
using DevExpress.Xpf.Ribbon;
using CardWorkbench.Utils;

namespace CardWorkbench
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : DXRibbonWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            new NavBarDragDropHelper(toolBoxNavBar);  //注册右侧导航工具栏可拖动

        }

    }
}
<file_sep>﻿using DevExpress.Xpf.Core.Native;
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.Input;

namespace CardWorkbench.Utils
{
    /// <summary>
    /// 界面UI控件工具类
    /// </summary>
    public class UIControlHelper
    {
        /// <summary>
        /// 使点击的控件在容器中置顶
        /// </summary>
        /// <param name="e">鼠标点击event参数</param>
        /// <param name="containerName">容器名称</param>
        public static void setClickedUserControl2TopIndex(MouseButtonEventArgs e,string containerName)
        {
            UserControl parentControl = LayoutHelper.FindParentObject<UserControl>(e.Source as DependencyObject);
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);
            Canvas workCanvas = (Canvas)LayoutHelper.FindElementByName(root, containerName);
            BringToFront(workCanvas as FrameworkElement, parentControl);
        }
        /// <summary>
        /// 获得容器中顶层控件的zindex值
        /// </summary>
        /// <param name="element">容器</param>
        /// <returns></returns>
        public static int getMaxZIndexOfContainer(FrameworkElement element)
        {
            if (element == null) return -1;

            Canvas canvas = element as Canvas;
            if (canvas == null) return -1;

            if (canvas.Children == null || canvas.Children.Count == 0)
            {
                return 0;
            }

            var maxZ = canvas.Children.OfType<UIElement>()
                //.Where(x => x != pane)
             .Select(x => Canvas.GetZIndex(x))
             .Max();

            return maxZ;
        }

        /// <summary>
        /// 在容器中置顶指定控件
        /// </summary>
        /// <param name="element">容器</param>
        /// <param name="pane">需要置顶的控件</param>
        public static void BringToFront(FrameworkElement element, Control pane)
        {
            int maxZ = getMaxZIndexOfContainer(element);
            if (maxZ == -1)
            {
                return;
            }
            Canvas.SetZIndex(pane, maxZ + 1);
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace CardWorkbench.Models
{
    public class FrameModel 
    {
        public int FrameID { get; set; }

        public string SyncWord { get; set; }
        public string Word1 { get; set; }
        public string Word2 { get; set; }
        public string Word3 { get; set; }
        public string ID { get; set; }
        public string Word5 { get; set; }
        public string Word6 { get; set; }
        public string Word7 { get; set; }
        public string Word8 { get; set; }
        public string Word9 { get; set; }
        public string Word10 { get; set; }
        public string Word11 { get; set; }
        public string Word12 { get; set; }

    }

    public static class FrameTestCase
    {
        public static IList<FrameModel> generateData()
        {
            List<FrameModel> frameModelList = new List<FrameModel>();
            for (int i = 1; i < 9; i++)
            {
                frameModelList.Add(new FrameModel() { FrameID = i, SyncWord = "EB101", Word1 = "CODE", Word2 = "CODE", Word3 = "CODE", ID = i + "", Word5 = "CODE", Word6 = "CODE", Word7 = "CODE", Word8 = "CODE", Word9 = "CODE", Word10 = "CODE", Word11 = "CODE", Word12 = "CODE" });
            }
            return frameModelList;

        }
    }
}
<file_sep>﻿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.Navigation;
using System.Windows.Shapes;

namespace CardWorkbench.Views.MenuControls
{
    /// <summary>
    /// ReceiverUC.xaml 的交互逻辑
    /// </summary>
    public partial class ReceiverUC : UserControl
    {
        //Grid增加border边线
        public void AddGridBorder()
          {
              int rows = MainGrid.RowDefinitions.Count;
              int columns = MainGrid.ColumnDefinitions.Count;
              //TagButton btnTag = new TagButton();
              for (int i = 0; i < rows; i++)
             {
                 if (i != rows - 1)
                 {
                     #region
 
                     for (int j = 0; j < columns; j++)
                     {
                         Border border = null;
                         if (j == columns - 1)
                         {
                             border = new Border()
                             {
                                 BorderBrush = new SolidColorBrush(Colors.Gray),
                                 BorderThickness = new Thickness(1, 1, 1, 0)
                             };
                         }
                         else
                         {
                             border = new Border()
                             {
                                 BorderBrush = new SolidColorBrush(Colors.Gray),
                                 BorderThickness = new Thickness(1, 1, 0, 0)                                
                             };
                         }
                         Grid.SetRow(border, i);
                         Grid.SetColumn(border, j);
                         MainGrid.Children.Add(border);
                     }
                     #endregion
                 }
                 else
                 {
                     for (int j = 0; j < columns; j++)
                     {
                         Border border = null;
                         if (j + 1 != columns)
                         {
                             border = new Border
                             {
                                 BorderBrush = new SolidColorBrush(Colors.Gray),
                                 BorderThickness = new Thickness(1, 1, 0, 1)
                             };
                         }
                         else
                         {
                             border = new Border
                             {
                                 BorderBrush = new SolidColorBrush(Colors.Gray),
                                BorderThickness = new Thickness(1, 1, 1, 1)
                             };
                         }
                         Grid.SetRow(border, i);
                         Grid.SetColumn(border, j);
                         MainGrid.Children.Add(border);
                     }
                 }
             }
         }

        public ReceiverUC()
        {
            InitializeComponent();
            AddGridBorder();
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardWorkbench.Models
{
    /// <summary>
    /// 参数分类实体
    /// </summary>
    public class ParamSortType
    {
        public int paramSortTypeId { get; set; }

        public string paramSortTypeName { get; set; }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardWorkbench.ViewModels.MenuControls
{
    public class FrameSyncUCViewModel : MenuControlsViewModel
    {
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardWorkbench.Models
{
    /// <summary>
    /// 校准类型实体类
    /// </summary>
    public class CalibrateType
    {
        public int calibrateTypeId { get; set; }

        public string calibrateTypeName { get; set; }
    }
}
<file_sep>﻿using DevExpress.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardWorkbench.ViewModels.CommonControls
{
    /// <summary>
    /// 自定义控件时间ViewModel类
    /// </summary>
    public class TimeControlViewModel : CommonControlViewModel
    {
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
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 DevExpress.Xpf.Grid.Core;
using CardWorkbench.Models;
using System.Windows.Controls;

namespace CardWorkbench.Views.CommonTools
{
    /// <summary>
    /// FrameDump.xaml 的交互逻辑
    /// </summary>
    public partial class FrameDump : UserControl
    {
        public static List<FrameModel> frames = new List<FrameModel>();

        public FrameDump()
        {
            InitializeComponent();
            insertRows();

         }
        public void insertRows()
        {
            frameGrid.ItemsSource = FrameTestCase.generateData();
        }
    }
}
<file_sep>﻿using CardWorkbench.Utils;
using DevExpress.Mvvm;
using DevExpress.Xpf.Charts;
using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.Gauges;
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.Input;

namespace CardWorkbench.ViewModels.CommonControls
{
    /// <summary>
    /// 自定义控件圆形仪表ViewModel类
    /// </summary>
    public class CirleControlViewModel : CommonControlViewModel
    {
       
        
    }
}
<file_sep>﻿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 DevExpress.Xpf.Docking;

namespace CardWorkbench.Views.CommonTools
{
    /// <summary>
    /// BitSyncControlPanel.xaml 的交互逻辑
    /// </summary>
    public partial class BitSyncControlPanel : UserControl
    {
        public BitSyncControlPanel()
        {
            InitializeComponent();
            this.LayoutPanel.Caption = "位同步控件";
        }
    }
}
<file_sep>﻿using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.Editors;
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.Navigation;
using System.Windows.Shapes;

namespace CardWorkbench.Views.MenuControls
{
    /// <summary>
    /// PlayBack.xaml 的交互逻辑
    /// </summary>
    public partial class PlayBack : UserControl
    {
        public PlayBack()
        {
            InitializeComponent();
        }

        private void ButtonInfo_Click(object sender, RoutedEventArgs e)
        {
            ButtonEdit be = LayoutHelper.FindLayoutOrVisualParentObject<ButtonEdit>(sender as DependencyObject, true);
            if (be == null)
                return;
            System.Windows.Forms.FileDialog dialog = new System.Windows.Forms.OpenFileDialog();
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                
                be.EditValue = dialog.FileName;
            }
        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardWorkbench.Models
{
    public class HardwareModel
    {
        //板卡ID
        public int cardID { get; set; }

        //板卡型号
        public string cardModel { get; set; }

        //板卡功能描述
        public string cardDescription { get; set; }

        //todo: 板卡组成对象
       
    }

    public static class HardwareModelTestCase
    {
        public static IList<HardwareModel> generateData()
        {
            List<HardwareModel> hardwareList = new List<HardwareModel>();
            for (int i = 1; i < 6; i++)
            {
                hardwareList.Add(new HardwareModel() { cardID = i, cardModel = "GDP4425", cardDescription = "接收机，未同步，帧同步，模拟" });
            }
            return hardwareList;

        }
    }
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;


namespace CardWorkbench.Models
{
    /// <summary>
    /// 参数实体类
    /// </summary>
    public class Param
    {
        public int paramId { get; set; }

        [DisplayName("CalibrateType")]
        public int calibrateTypeId { get; set; }

        [DisplayName("ParamSortType")]
        public int paramSortTypeId { get; set; }

        public string paramName { get; set; }

        public string paramChineseName { get; set; }

        public virtual CalibrateType calibrateType { get; set; }
        public virtual ParamSortType paramSortType { get; set; }
    }

    /// <summary>
    /// 测试数据
    /// </summary>
    public static class SampleData
    {
        public static List<Param> paramList { get; set; }
        public static List<CalibrateType> calibrateTypeList { get; set; }
        public static List<ParamSortType> paramSortTypeList { get; set; }
        public static void initData()   //初始化数据
        {
            if (paramList != null)
            {
                return;
            }

            calibrateTypeList = new List<CalibrateType>
            {
                new CalibrateType { calibrateTypeName = "点对校准" },
                new CalibrateType { calibrateTypeName = "多项式校准" }
              
                };

            int i = 0;
            calibrateTypeList.ForEach(x => x.calibrateTypeId = ++i);

            paramSortTypeList = new List<ParamSortType>
            {
                    new ParamSortType { paramSortTypeName = "飞控" },
                    new ParamSortType { paramSortTypeName = "航电" },
                    new ParamSortType { paramSortTypeName = "USDC" },
                    new ParamSortType { paramSortTypeName = "IDMP" },
                    new ParamSortType { paramSortTypeName = "其它" }

            };
            i = 0;
            paramSortTypeList.ForEach(x => x.paramSortTypeId = ++i);

            paramList = new List<Param>
            {
                new Param { paramName = "Rock" , paramChineseName = "名称1", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Jazz" , paramChineseName = "名称2" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "航电") },
                new Param { paramName = "Metal" , paramChineseName = "名称3" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "IDMP") },
                new Param { paramName = "Alternative" , paramChineseName = "名称4" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Disco" , paramChineseName = "名称5"  , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "IDMP") },
                new Param { paramName = "Blues" , paramChineseName = "名称6" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "航电") },
                new Param { paramName = "Latin" , paramChineseName = "名称7" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "USDC") },
                new Param { paramName = "Reggae" , paramChineseName = "名称8" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Pop" , paramChineseName = "名称9", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Classical" , paramChineseName = "名称10", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "USDC") },
                   new Param { paramName = "Rock" , paramChineseName = "名称1", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "ID" , paramChineseName = "ID参数" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "其它") },
                new Param { paramName = "Metal" , paramChineseName = "名称3" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "IDMP") },
                new Param { paramName = "Alternative" , paramChineseName = "名称4" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Disco" , paramChineseName = "名称5"  , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "IDMP") },
                new Param { paramName = "Blues" , paramChineseName = "名称6" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "航电") },
                new Param { paramName = "Latin" , paramChineseName = "名称7" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "USDC") },
                new Param { paramName = "Reggae" , paramChineseName = "名称8" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Pop" , paramChineseName = "名称9", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Classical" , paramChineseName = "名称10", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "USDC") },
                    new Param { paramName = "Rock" , paramChineseName = "名称1", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Jazz" , paramChineseName = "名称2" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "航电") },
                new Param { paramName = "Metal" , paramChineseName = "名称3" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "IDMP") },
                new Param { paramName = "Alternative" , paramChineseName = "名称4" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Disco" , paramChineseName = "名称5"  , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "IDMP") },
                new Param { paramName = "Blues" , paramChineseName = "名称6" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "航电") },
                new Param { paramName = "Latin" , paramChineseName = "名称7" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "USDC") },
                new Param { paramName = "Reggae" , paramChineseName = "名称8" , 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Pop" , paramChineseName = "名称9", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "多项式校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "飞控") },
                new Param { paramName = "Classical" , paramChineseName = "名称10", 
                    calibrateType = calibrateTypeList.Single(a => a.calibrateTypeName == "点对校准"),
                    paramSortType = paramSortTypeList.Single(a => a.paramSortTypeName == "USDC") }
            };

            
        }
    }
}
<file_sep>﻿using CardWorkbench.Views.CommonControls;
using CardWorkbench.Views.CommonTools;
using CardWorkbench.Utils;
using DevExpress.Mvvm;
using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.Docking;
using DevExpress.Xpf.NavBar;
using DevExpress.Xpf.Ribbon;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using CardWorkbench.Models;
using DevExpress.Xpf.Editors;
using System.Windows.Threading;
using System.Windows.Media;
using DevExpress.Data;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Bars;
using CardWorkbench.Views.MenuControls;
using CardWorkbench.Views.CardStateGroup;
using System.Threading;
using DevExpress.Xpf.Core;

namespace CardWorkbench.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
      //控件名称
      public static readonly string TOOLBOX_TEXTCONTROL_NAME = "toolbox_textCtrl"; //文本
      public static readonly string TOOLBOX_LINECONTROL_NAME = "toolbox_lineCtrl"; //二维曲线
      public static readonly string TOOLBOX_METERCONTROL_NAME = "toolbox_meterCtrl"; //仪表
      public static readonly string TOOLBOX_LIGHTCONTROL_NAME = "toolbox_lightCtrl"; //工作灯
      public static readonly string TOOLBOX_TIMECONTROL_NAME = "toolbox_timeCtrl"; //时间
      //工作区document group 名称
      public static readonly string DOCUMENTGROUP_NAME = "documentContainer";
      //工作区自定义控件Canvas名称
      public static readonly string CANVAS_CUSTOM_CONTROL_NAME = "workCanvas";
      //Ribbon标签栏及其组件名称
      public static readonly string RIBBONCONTROL_NAME = "ribbonControl";
      public static readonly string RIBBONPAGE_TOOLS_NAME = "toolsRibbonPage";  
      //工具panel名称、标题 
      public static readonly string PANEL_FRAMEDUMP_NAME = "frameDumpPanel";
      public static readonly string PANEL_FRAMEDUMP_CAPTION = "原始帧显示";
      public static readonly string PANEL_RECEIVERCHART_NAME = "receiverChartPanel";
      public static readonly string PANEL_RECEIVERCHART_CAPTION = "接收机波形显示";     
      public static readonly string PANEL_BITSYNCCHART_NAME = "bitSyncChartPanel";
      public static readonly string PANEL_BITSYNCCHART_CAPTION = "位同步波形显示";
      public static readonly string PANEL_DECOMOUTPUT_NAME = "decomOutputPanel";
      public static readonly string PANEL_DECOMOUTPUT_CAPTION = "解码输出";
      public static readonly string PANEL_CUSTOMCONTROL_NAME = "mainControl";  //自定义控件     
      public static readonly string DOCUMENTPANEL_WORKSTATE_NAME = "document1"; //工作区硬件工作状态panel名称
      //硬件设置菜单栏对话框名称
      public static readonly string DIALOG_HARDWAR_RECOGNITION_NAME = "hardwareRecognitionDialog";
      public static readonly string DIALOG_RECEIVER_SETTING_NAME = "receiverSettingDialog";  //接收机设置
      public static readonly string DIALOG_BITSYNC_SETTING_NAME = "bitSyncSettingDialog";  //位同步设置
      public static readonly string DIALOG_FRAMESYNC_SETTING_NAME = "frameSyncSettingDialog"; //帧同步设置
      public static readonly string DIALOG_TIME_SETTING_NAME = "timeSettingDialog"; //时间设置
      public static readonly string DIALOG_PLAYBACK_SETTING_NAME = "playBackSettingDialog"; //回放设置

       
      //注册服务声明
      public IDialogService hardwareRecognitionDialogService { get { return GetService<IDialogService>(DIALOG_HARDWAR_RECOGNITION_NAME); } }  //获得硬件识别对话框服务

      public IDialogService receiverSettingDialogService { get { return GetService<IDialogService>(DIALOG_RECEIVER_SETTING_NAME); } }  //获得接收机设置对话框服务

      public IDialogService bitSyncSettingDialogService { get { return GetService<IDialogService>(DIALOG_BITSYNC_SETTING_NAME); } }  //获得位同步设置对话框服务

      public IDialogService frameSyncSettingDialogService { get { return GetService<IDialogService>(DIALOG_FRAMESYNC_SETTING_NAME); } }  //获得帧同步设置对话框服务

      public IDialogService timeSettingDialogService { get { return GetService<IDialogService>(DIALOG_TIME_SETTING_NAME); } }  //获得时间同步设置对话框服务

      public IDialogService playBackSettingDialogService { get { return GetService<IDialogService>(DIALOG_PLAYBACK_SETTING_NAME); } }  //获得模拟回放设置对话框服务
      public IOpenFileDialogService OpenFileDialogService { get { return GetService<IOpenFileDialogService>() ; } }  //获得文件选择对话框服务
      public ISplashScreenService SplashScreenService { get { return GetService<ISplashScreenService>(); } } //LOADING splash screen服务

        //参数实体类列表
      public List<Param> paramList { get; set; }
      public List<CalibrateType> calibrateTypeList { get; set; }
      public List<ParamSortType> paramSortTypeList { get; set; }

      //参数grid某行是否拖拽开始
      bool _dragStarted = false;
      //参数grid面板table view的名称
      public static readonly string PARAM_GRID_TABLEVIEW_NAME = "paramGridTabelView"; 

      public MainWindowViewModel() {
          //初始化参数数据
          SampleData.initData();
          paramList = SampleData.paramList;
          calibrateTypeList = SampleData.calibrateTypeList;
          paramSortTypeList = SampleData.paramSortTypeList;

          //
      }


      #region 顶部功能菜单命令绑定  
 
      /// <summary>
      /// 硬件识别对话框命令
      /// </summary>
      public ICommand hardwareRecognitionCommand
      {
          get { return new DelegateCommand<LayoutPanel>(onHardwareRecognitionClick, x => { return true; }); }
      }

      private void onHardwareRecognitionClick(LayoutPanel cardMenuPanel)
      {
          UICommand okCommand = new UICommand()
          {
              Caption = "确定",
              IsCancel = false,
              IsDefault = true,
              Command = new DelegateCommand<CancelEventArgs>(
                 x => { },
                 true
              ),
          };
          UICommand cancelCommand = new UICommand()
          {
              Id = MessageBoxResult.Cancel,
              Caption = "取消",
              IsCancel = true,
              IsDefault = false,
          };
          UICommand result = hardwareRecognitionDialogService.ShowDialog(
              dialogCommands: new List<UICommand>() { okCommand, cancelCommand },
              title: "硬件识别",
              viewModel: null
          );

          if (result == okCommand)
          {
              //cardMenuConfigPanel
              onSelectHardwareLoad(cardMenuPanel);
          }
      }

      /// <summary>
      /// 加载选中板卡显示配置菜单命令
      /// </summary>
      private void onSelectHardwareLoad(LayoutPanel cardMenuPanel)
      {
          cardMenuPanel.Content = new CardMenuConfig();

          FrameworkElement root = LayoutHelper.GetRoot(cardMenuPanel);
          //TEST 显示主页硬件状态////////////////////////////////////////////////
          GroupBox receiverGrpBox = (GroupBox)root.FindName("groupBox_recState");
          GroupBox bitSyncGrpBox = (GroupBox)root.FindName("groupBox_bitSyncState");
          GroupBox frameSyncGrpBox = (GroupBox)root.FindName("groupBox_frameSyncState");
          receiverGrpBox.Content = new ReceiverStateGroupBox();
          bitSyncGrpBox.Content = new BitSyncStateGroupBox();
          frameSyncGrpBox.Content = new FrameSyncStateGroupBox();
          ////////////////////////////////////////////////////
          //开启ribbon工具标签页
          RibbonControl ribbonControl = (RibbonControl)LayoutHelper.FindElementByName(root, RIBBONCONTROL_NAME);
          RibbonPage ribbonPage = ribbonControl.Manager.FindName(RIBBONPAGE_TOOLS_NAME) as RibbonPage;
          ribbonPage.IsEnabled = true;
      }

      /// <summary>
      /// 打开读取本地硬件配置文件对话框
      /// </summary>
      public ICommand openHardwareConfigCommand {
          get { return new DelegateCommand<LayoutPanel>(onOpenHardwareConfigClick, x => { return true; }); }
      }

      private void onOpenHardwareConfigClick(LayoutPanel cardMenuPanel)
      {
          //System.Windows.Forms.FileDialog dialog = new System.Windows.Forms.OpenFileDialog();
          //if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
          //{
          //    onSelectHardwareLoad(cardMenuPanel);
          //}
          OpenFileDialogService.Filter = "配置文件|*.xml";
          OpenFileDialogService.FilterIndex = 1;
          bool DialogResult = OpenFileDialogService.ShowDialog();
          if (!DialogResult)
          {
              //ResultFileName = string.Empty;
          }
          else
          {
              onSelectHardwareLoad(cardMenuPanel);

              //IFileInfo file = OpenFileDialogService.Files.First();
              //ResultFileName = file.Name;
              //using (var stream = file.OpenText())
              //{
              //    FileBody = stream.ReadToEnd();
              //}
          }
      }

      /// <summary>
      /// ”原始帧显示“ 按钮Command
      /// </summary>
      public ICommand frameDumpCommand {
          get { return new DelegateCommand<DockLayoutManager>(onFrameDumpClick, x => { return true; }); }
      }

      private void onFrameDumpClick(DockLayoutManager dockManager)
      {
          createWorkDocumentPanel(dockManager, DOCUMENTGROUP_NAME, PANEL_FRAMEDUMP_NAME, PANEL_FRAMEDUMP_CAPTION, new FrameDump());          
      }

      /// <summary>
      /// "接收机波形显示" 按钮command
      /// </summary>
      public ICommand receiverChartCommand
      {
          get { return new DelegateCommand<DockLayoutManager>(onReceiverChartClick, x => { return true; }); }
      }

      private void onReceiverChartClick(DockLayoutManager dockManager)
      {
          createWorkDocumentPanel(dockManager, DOCUMENTGROUP_NAME, PANEL_RECEIVERCHART_NAME, PANEL_RECEIVERCHART_CAPTION, new ReceiverChartControl());
      }

      /// <summary>
      /// "位同步波形显示" 按钮Command
      /// </summary>
      public ICommand bitSyncChartCommand
      {
          get { return new DelegateCommand<DockLayoutManager>(onBitSyncChartClick, x => { return true; }); }
      }

      private void onBitSyncChartClick(DockLayoutManager dockManager)
      {
          createWorkDocumentPanel(dockManager, DOCUMENTGROUP_NAME, PANEL_BITSYNCCHART_NAME, PANEL_BITSYNCCHART_CAPTION, new BitSyncChart());
      }

      /// <summary>
      /// ”解码输出“ 按钮Command
      /// </summary>
      public ICommand decomOutputCommand
      {
          get { return new DelegateCommand<DockLayoutManager>(onDecomOutputClick, x => { return true; }); }
      }

      private void onDecomOutputClick(DockLayoutManager dockManager)
      {
          createWorkDocumentPanel(dockManager, DOCUMENTGROUP_NAME, PANEL_DECOMOUTPUT_NAME, PANEL_DECOMOUTPUT_CAPTION, new DecomOutputPanel());
      }

      /// <summary>
      /// "自定义控件" 按钮Command
      /// </summary>
      public ICommand customControlCommand {
          get { return new DelegateCommand<DockLayoutManager>(onCustomControlClick, x => { return true; }); }
      }
      private void onCustomControlClick(DockLayoutManager dockManager)
      {
          DocumentGroup documentGroup = dockManager.GetItem(DOCUMENTGROUP_NAME) as DocumentGroup;
          DocumentPanel docPanel = dockManager.GetItem(PANEL_CUSTOMCONTROL_NAME) as DocumentPanel;
          if (docPanel != null && docPanel.IsClosed)
          {
              dockManager.DockController.Restore(docPanel);
          }
          dockManager.DockController.Activate(docPanel);
      }

      /// <summary>
      /// 在工作区document group创建新的document Panel
      /// </summary>
      /// <param name="dockManager">dock布局管理器</param>
      /// <param name="documentGroupName">documentGroup名称</param>
      /// <param name="addDocPanelName">新增Document panel名称</param>
      /// <param name="addDocPanelCaption">新增Document Panel显示标题</param>
      /// <param name="panelContent">新增Document Panel的内容元素</param>
      private void createWorkDocumentPanel(DockLayoutManager dockManager, string documentGroupName, string addDocPanelName, string addDocPanelCaption, object panelContent)
      {
          DocumentGroup documentGroup = dockManager.GetItem(documentGroupName) as DocumentGroup;
          DocumentPanel docPanel = dockManager.GetItem(addDocPanelName) as DocumentPanel;
          if (docPanel == null)
          {
              docPanel = dockManager.DockController.AddDocumentPanel(documentGroup);
              docPanel.Caption = addDocPanelCaption;
              docPanel.Content = panelContent;
              docPanel.Name = addDocPanelName;
          }
          else if (docPanel.IsClosed)
          {
              dockManager.DockController.Restore(docPanel);
          }
          dockManager.DockController.Activate(docPanel);
      }
      #endregion

      #region 硬件设置对话框命令绑定

      /// <summary>
      /// 接收机设置对话框命令
      /// </summary>
      public ICommand receiverSettingCommand
      {
          get { return new DelegateCommand<object>(onReceiverSettingClick, x => { return true; }); }
      }

      private void onReceiverSettingClick(object context)
      {
          DXSplashScreen.Show<SplashScreenView>(); //显示loading框

          UICommand okCommand = new UICommand()
          {
              Caption = "确定",
              IsCancel = false,
              IsDefault = true,
              Command = new DelegateCommand<CancelEventArgs>(
                 x => { },
                 true
              ),
          };
          UICommand cancelCommand = new UICommand()
          {
              Id = MessageBoxResult.Cancel,
              Caption = "取消",
              IsCancel = true,
              IsDefault = false,
          };
          //DXSplashScreen.Show<SplashScreenView>();
          UICommand result = receiverSettingDialogService.ShowDialog(
              dialogCommands: new List<UICommand>() { okCommand, cancelCommand },
              title: "接收机设置",
              viewModel: null
          );

          if (result == okCommand)
          {
              MessageBox.Show("successfull!!");
          }
      }

      /// <summary>
      /// 位同步设置对话框命令
      /// </summary>
      public ICommand bitSyncSettingCommand
      {
          get { return new DelegateCommand<object>(onBitSyncSettingClick, x => { return true; }); }
      }

      private void onBitSyncSettingClick(object context)
      {
          DXSplashScreen.Show<SplashScreenView>(); //显示loading框
          UICommand okCommand = new UICommand()
          {
              Caption = "确定",
              IsCancel = false,
              IsDefault = true,
              Command = new DelegateCommand<CancelEventArgs>(
                 x => { },
                 true
              ),
          };
          UICommand cancelCommand = new UICommand()
          {
              Id = MessageBoxResult.Cancel,
              Caption = "取消",
              IsCancel = true,
              IsDefault = false,
          };
          UICommand result = bitSyncSettingDialogService.ShowDialog(
              dialogCommands: new List<UICommand>() { okCommand, cancelCommand },
              title: "位同步设置",
              viewModel: null
          );

          if (result == okCommand)
          {
              MessageBox.Show("successfull!!");
          }
      }

     /// <summary>
      /// 帧同步设置对话框命令
     /// </summary>
      public ICommand frameSyncSettingCommand
      {
          get { return new DelegateCommand<object>(onFrameSyncSettingClick, x => { return true; }); }
      }

      private void onFrameSyncSettingClick(object context)
      {
          DXSplashScreen.Show<SplashScreenView>(); //显示loading框

          UICommand okCommand = new UICommand()
          {
              Caption = "确定",
              IsCancel = false,
              IsDefault = true,
              Command = new DelegateCommand<CancelEventArgs>(
                 x => { },
                 true
              ),
          };
          UICommand cancelCommand = new UICommand()
          {
              Id = MessageBoxResult.Cancel,
              Caption = "取消",
              IsCancel = true,
              IsDefault = false,
          };
          UICommand result = frameSyncSettingDialogService.ShowDialog(
              dialogCommands: new List<UICommand>() { okCommand, cancelCommand },
              title: "帧同步设置",
              viewModel: null
          );

          if (result == okCommand)
          {
              MessageBox.Show("successfull!!");
          }
      }

      /// <summary>
      /// 时间同步设置对话框命令
      /// </summary>
      public ICommand timeSettingCommand
      {
          get { return new DelegateCommand<object>(ontimeSyncSettingClick, x => { return true; }); }
      }
      private void ontimeSyncSettingClick(object context)
      {
          DXSplashScreen.Show<SplashScreenView>(); //显示loading框

          UICommand okCommand = new UICommand()
          {
              Caption = "确定",
              IsCancel = false,
              IsDefault = true,
              Command = new DelegateCommand<CancelEventArgs>(
                 x => { },
                 true
              ),
          };
          UICommand cancelCommand = new UICommand()
          {
              Id = MessageBoxResult.Cancel,
              Caption = "取消",
              IsCancel = true,
              IsDefault = false,
          };
          UICommand result = timeSettingDialogService.ShowDialog(
              dialogCommands: new List<UICommand>() { okCommand, cancelCommand },
              title: "时间同步设置",
              viewModel: null
          );

          if (result == okCommand)
          {
              MessageBox.Show("successfull!!");
          }
      }

      /// <summary>
      /// 模拟回放设置对话框命令
      /// </summary>
      public ICommand playBackSettingCommand
      {
          get { return new DelegateCommand<object>(onPlayBackSettingClick, x => { return true; }); }
      }
      private void onPlayBackSettingClick(object context)
      {
          DXSplashScreen.Show<SplashScreenView>(); //显示loading框

          UICommand okCommand = new UICommand()
          {
              Caption = "确定",
              IsCancel = false,
              IsDefault = true,
              Command = new DelegateCommand<CancelEventArgs>(
                 x => { },
                 true
              ),
          };
          UICommand cancelCommand = new UICommand()
          {
              Id = MessageBoxResult.Cancel,
              Caption = "取消",
              IsCancel = true,
              IsDefault = false,
          };
          UICommand result = playBackSettingDialogService.ShowDialog(
              dialogCommands: new List<UICommand>() { okCommand, cancelCommand },
              title: "模拟回放设置",
              viewModel: null
          );

          if (result == okCommand)
          {
              MessageBox.Show("successfull!!");
          }
      }
      #endregion

      #region 控件栏拖拽命令绑定
        public ICommand dropToolBoxCommand
        {
            get { return new DelegateCommand<DragEventArgs>(onDropToolBoxNavItem, x => { return true; }); }
        }


        //拖拽事件
        private void onDropToolBoxNavItem(DragEventArgs e)
        {
            object originalSource = e.OriginalSource;
            NavBarItemControl item = LayoutHelper.FindParentObject<NavBarItemControl>(originalSource as DependencyObject);
            NavBarGroupHeader header = LayoutHelper.FindParentObject<NavBarGroupHeader>(originalSource as DependencyObject);
            NavBarItem data = e.Data.GetData(NavBarDragDropHelper.FormatName) as NavBarItem;
            if (data != null && data.Name != null)
            {
                string navItemName = data.Name;
                FrameworkElement root = LayoutHelper.GetTopLevelVisual(originalSource as DependencyObject);
                Canvas workCanvas = (Canvas)LayoutHelper.FindElementByName(root, CANVAS_CUSTOM_CONTROL_NAME);
                UserControl commonControl = null;
                int maxZindex = UIControlHelper.getMaxZIndexOfContainer(workCanvas);
                if (TOOLBOX_TEXTCONTROL_NAME.Equals(navItemName))   //文本控件
                {
                    commonControl = new TextControl();

                }
                else if (TOOLBOX_LINECONTROL_NAME.Equals(navItemName)) //曲线控件
                {
                    commonControl = new ChartControl();
                }
                else if (TOOLBOX_LIGHTCONTROL_NAME.Equals(navItemName)) //工作灯控件
                {
                    commonControl = new LampControl();
                }
                else if (TOOLBOX_METERCONTROL_NAME.Equals(navItemName))  //仪表控件
                {
                    commonControl = new CirleControl();
                }
                else if (TOOLBOX_TIMECONTROL_NAME.Equals(navItemName)) //时间控件
                {
                    commonControl = new TimeControl();
                }
                if (commonControl != null)
                {
                    Canvas.SetZIndex(commonControl, maxZindex + 1);
                    workCanvas.Children.Add(commonControl);                   
                }

            }
        }
      #endregion

      #region 参数Grid面板命令绑定
        public ICommand ParamGridMouseDownCommand
        {
            get { return new DelegateCommand<MouseButtonEventArgs>(onParamGridMouseDown, x => { return true; }); }
        }

        private void onParamGridMouseDown(MouseButtonEventArgs e)
        {
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);
            TableView paramTableView = (TableView)LayoutHelper.FindElementByName(root, PARAM_GRID_TABLEVIEW_NAME);
            int rowHandle = paramTableView.GetRowHandleByMouseEventArgs(e);
            if (rowHandle != GridDataController.InvalidRow)
                _dragStarted = true;
        }

        public ICommand ParamGridMouseMoveCommand
        {
            get { return new DelegateCommand<MouseEventArgs>(onParamGridMouseMove, x => { return true; }); }
        }

        private void onParamGridMouseMove(MouseEventArgs e)
        {
            FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);
            TableView paramTableView = (TableView)LayoutHelper.FindElementByName(root, PARAM_GRID_TABLEVIEW_NAME);
            //int rowHandle = paramTableView.GetRowHandleByMouseEventArgs(e);
            //RowControl rowControl = paramTableView.GetRowElementByRowHandle(rowHandle) as RowControl;

            //此处必须新建控件的dipatcher线程做处理，否则在拖动参数时会出现界面假死的情况
            paramTableView.Dispatcher.BeginInvoke(new Action(() =>
            {
                if (_dragStarted)
                {
                    //Console.WriteLine("start..............");
                    FrameworkElement element = paramTableView.GetRowElementByMouseEventArgs(e);
                    RowData rowData = null;
                    if (element != null)
                    {
                        rowData = element.DataContext as RowData;
                        if (rowData == null)
                        {
                            return;
                        }
                        DataObject data = CreateDataObject(rowData);
                        DragDrop.DoDragDrop(element, data, DragDropEffects.Move | DragDropEffects.Copy);
                    }
                    _dragStarted = false;
                    //Console.WriteLine("end..............");
                }
            }));

        }

        private DataObject CreateDataObject(RowData rowData)
        {
            DataObject data = new DataObject();
            //data.SetData(typeof(int), rowHandle);
            data.SetData(typeof(RowData), rowData);
            return data;
        }

        #endregion

      #region 自定义控件Panel按钮命令绑定
        public ICommand resetCommonControlsPanelCommand
        {
            get { return new DelegateCommand<Canvas>(onResetCommonControlsBtnClick, x => { return true; }); }
        }

        private void onResetCommonControlsBtnClick(Canvas commonControlsCanvas)
        {
            if (commonControlsCanvas != null)
            {
                commonControlsCanvas.Children.Clear();
            }
        }

        /// <summary>
        /// 控件键盘按键响应事件命令
        /// </summary>
        public ICommand CanvasDeleteKeyDownCommand
        {
            get { return new DelegateCommand<KeyEventArgs>(onCanvasDeleteKeyDown, x => { return true; }); }
        }

        private void onCanvasDeleteKeyDown(KeyEventArgs e)
        {
            if (e.Key == Key.Delete)  //删除按键
            {
                //UserControl control = LayoutHelper.FindParentObject<UserControl>(e.Source as DependencyObject);
               // FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);
                Canvas workCanvas = e.Source as Canvas;
                if (workCanvas == null)
                {
                    FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);
                    workCanvas = (Canvas)LayoutHelper.FindElementByName(root, CANVAS_CUSTOM_CONTROL_NAME);

                }
                var maxZ = UIControlHelper.getMaxZIndexOfContainer(workCanvas); //当前最顶层的控件

                if (workCanvas.Children.Count != 0)
                {
                    foreach (FrameworkElement childElement in workCanvas.Children)
                    {
                        if (Canvas.GetZIndex(childElement) == maxZ)
                        {
                            workCanvas.Children.Remove(childElement); //删除
                            break;
                        }

                    }

                }
            }
        }
        #endregion
    }
}
<file_sep>﻿using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.NavBar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;

namespace CardWorkbench.Utils
{
    /// <summary>
    /// 导航栏拖放工具类
    /// </summary>
    class NavBarDragDropHelper
    {
        private System.Windows.Point _MouseDownLocation;
        private readonly NavBarControl _NavBar;
        public const string FormatName = "NavBarDragFormat";  //定义一个drag动作临时DataObject名称



        public NavBarDragDropHelper(NavBarControl navBar)
        {
            _NavBar = navBar;
            _NavBar.PreviewMouseLeftButtonDown += _NavBar_PreviewMouseLeftButtonDown;   //左键按下方法
            _NavBar.PreviewMouseMove += _NavBar_PreviewMouseMove;   //鼠标移动方法
            _NavBar.AllowDrop = false;  //工具导航条本身不允许放置
            //_NavBar.DragOver += _NavBar_DragOver;
            //_NavBar.Drop += _NavBar_Drop;
        }




        void _NavBar_DragOver(object sender, DragEventArgs e)
        {
            //e.Effects = DragDropEffects.Copy;
            if (!e.Data.GetDataPresent(FormatName))
            {
                e.Effects = DragDropEffects.None;
            }
        }

        void _NavBar_Drop(object sender, DragEventArgs e)
        {
            object originalSource = e.OriginalSource;
            NavBarItemControl item = LayoutHelper.FindParentObject<NavBarItemControl>(originalSource as DependencyObject);
            NavBarGroupHeader header = LayoutHelper.FindParentObject<NavBarGroupHeader>(originalSource as DependencyObject);
            NavBarItem data = e.Data.GetData(FormatName) as NavBarItem;
            if (data != null)
            {
                NavBarItem navItem = item == null ? null : item.DataContext as NavBarItem;
                NavBarGroup group = navItem == null ? header.DataContext as NavBarGroup : navItem.Group;
                Console.WriteLine(navItem);

                OnDragDrop(navItem, group, data);
            }
        }

        void _NavBar_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _MouseDownLocation = e.GetPosition(null);
        }

        void _NavBar_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && CheckDiff(_MouseDownLocation - e.GetPosition(null)))
            {
                NavBarItemControl item = e.OriginalSource as NavBarItemControl;
                if (item == null)
                {
                    return;
                }
                NavBarItem navBarItem = item.DataContext as NavBarItem;
                DataObject dragData = new DataObject(FormatName, navBarItem);
                DragDrop.DoDragDrop(_NavBar, dragData, DragDropEffects.Copy);
            }
        }

        private static bool CheckDiff(Vector diff)
        {
            return (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
                                           Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance);
        }

        private void OnDragDrop(NavBarItem targetItem, NavBarGroup targetGroup, NavBarItem data)
        {
            DataRowView dataRowView = data.DataContext as DataRowView;
            DataTable sourceTable = dataRowView.DataView.Table;
            DataTable targetTable = (targetGroup.NavBar.ItemsSource as DataView).Table;
            DataRowView targetDataRow = targetItem == null ? null : targetItem.DataContext as DataRowView;
            int targetIndex = targetItem == null ? targetTable.Rows.Count : targetTable.Rows.IndexOf(targetDataRow.Row);
            DataRow newRow = targetTable.NewRow();
            newRow["Group"] = targetGroup.DataContext.ToString();
            newRow["Item"] = dataRowView["Item"];
            targetTable.Rows.InsertAt(newRow, targetIndex);
            sourceTable.Rows.Remove(dataRowView.Row);
            dataRowView.Delete();
            sourceTable.AcceptChanges();
        }
    }
}
<file_sep>﻿using DevExpress.Xpf.Charts;
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.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace CardWorkbench.Views.CommonTools
{
    /// <summary>
    /// EyeChart.xaml 的交互逻辑
    /// </summary>
    public partial class EyeChart : UserControl
    {
        private DispatcherTimer timer = new DispatcherTimer();
        private int number = 50;
        private int value = 1;
        private int interval = 1;
        public EyeChart()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromMilliseconds(100);
            timer.Tick += new EventHandler(RefreshPlot);
            timer.IsEnabled = true;
        }

        private void RefreshPlot(object sender,EventArgs e)
        {
            if(value>number)
            {
                value = 1;
            }else
            {
                value+=2;
            }
            SeriesPoint p = new SeriesPoint(interval, value);
            series.Points.Add(p);
            interval++;
            if(series.Points.Count>number)
            {
                series.Points.RemoveAt(0);
            }
        }
    }
}
<file_sep>﻿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 DevExpress.Xpf.NavBar;
using DevExpress.Xpf.Docking;

namespace CardWorkbench.Views.CommonTools
{
    /// <summary>
    /// WareTreeControl.xaml 的交互逻辑
    /// </summary>
    public partial class WareTreeControl : UserControl
    {
        public AutoHideGroup TargetGroup { get; set; }
        //public ReceiverControlPanel ReceiverPanel{get;set;}
        public BitSyncControlPanel BitPanel { get; set; }
        public WareTreeControl(AutoHideGroup targetGroup)
        {
            InitializeComponent();
            this.TargetGroup = targetGroup;
            //this.ReceiverPanel = new ReceiverControlPanel();
            this.BitPanel = new BitSyncControlPanel();
        }

        private void NavBarGroup_MouseDown(object sender, MouseButtonEventArgs e)
        {
            NavBarGroup selectGroup = (NavBarGroup)this.navcontrol.View.GetNavBarGroup(e);
            NavBarItem item = (NavBarItem)this.navcontrol.View.GetNavBarItem(e);
            if(item==null||item.Content==null)
            {
                return;
            }
            string value = (string)item.Content;
            if ("接收机".Equals(value))
            {
                if(this.TargetGroup.Items.Count>0)
                {
                    LayoutPanel panel = (LayoutPanel)this.TargetGroup.Items[0];
                    panel.Visibility = System.Windows.Visibility.Hidden;
                }
                this.TargetGroup.Items.Clear();
                //this.TargetGroup.Items.Add(this.ReceiverPanel.LayoutPanel);
                //this.ReceiverPanel.LayoutPanel.Visibility = System.Windows.Visibility.Visible;
            }else if("位同步".Equals(value))
            {
                if (this.TargetGroup.Items.Count > 0)
                {
                    LayoutPanel panel = (LayoutPanel)this.TargetGroup.Items[0];
                    panel.Visibility = System.Windows.Visibility.Hidden;
                }
                this.TargetGroup.Items.Clear();
                this.TargetGroup.Items.Add(this.BitPanel.LayoutPanel);
                this.BitPanel.LayoutPanel.Visibility = System.Windows.Visibility.Visible;
            }
        }

    }
}
<file_sep>﻿using CardWorkbench.Utils;
using DevExpress.Mvvm;
using DevExpress.Xpf.Core.Native;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace CardWorkbench.ViewModels.CommonControls
{

    /// <summary>
    /// 自定义控件通用ViewModel类
    /// </summary>
    public abstract class CommonControlViewModel : ViewModelBase
    {
        /// <summary>
        /// 控件点击事件命令
        /// </summary>
        public ICommand CommonControlClickCommand
        {
            get { return new DelegateCommand<MouseButtonEventArgs>(onCommonControlClick, x => { return true; }); }
        }

        private void onCommonControlClick(MouseButtonEventArgs e)
        {
            UIControlHelper.setClickedUserControl2TopIndex(e, MainWindowViewModel.CANVAS_CUSTOM_CONTROL_NAME);
        }

       

    }
}
<file_sep>﻿using DevExpress.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CardWorkbench.ViewModels.CommonControls
{
    /// <summary>
    /// 自定义控件指示灯ViewModel类
    /// </summary>
    public class LampControlViewModel : CommonControlViewModel
    {
    }
}
<file_sep>﻿using CardWorkbench.Models;
using CardWorkbench.Utils;
using DevExpress.Mvvm;
using DevExpress.Xpf.Charts;
using DevExpress.Xpf.Core.Native;
using DevExpress.Xpf.Grid;
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.Input;
using System.Windows.Threading;

namespace CardWorkbench.ViewModels.CommonControls
{
    /// <summary>
    ///  自定义控件曲线ViewModel类
    /// </summary>
    public class ChartControlViewModel : CommonControlViewModel
    {
        private DispatcherTimer timer = new DispatcherTimer();
        private int number = 50;
        private int value = 1;
        private int interval = 1;
        private LineSeries2D series2D = null;

        public ICommand ChartControlDragEnterCommand
        {
            get { return new DelegateCommand<DragEventArgs>(onChartControlDragEnter, x => { return true; }); }
        }

        private void onChartControlDragEnter(DragEventArgs e)
        {
            e.Effects = DragDropEffects.Copy;
            e.Handled = true;
        }

        public ICommand ChartControlDropCommand
        {
            get { return new DelegateCommand<DragEventArgs>(onChartControlDrop, x => { return true; }); }
        }

        private void onChartControlDrop(DragEventArgs e)
        {
            //int rowHandle = (int)e.Data.GetData(typeof(int));
            //MyObject myObject = (MyObject)grid1.GetRow(rowHandle);
            //MessageBox.Show("Hello"+rowHandle);
            RowData rowData = (RowData)e.Data.GetData(typeof(RowData));
            if (rowData != null)
            {
              //FrameworkElement root = LayoutHelper.GetTopLevelVisual(e.Source as DependencyObject);

              Pane chartPane = e.Source as Pane;
              XYDiagram2D xyDiagram2D = LayoutHelper.FindParentObject<XYDiagram2D>(chartPane as DependencyObject);
              ChartControl parentChartControl = LayoutHelper.FindParentObject<ChartControl>(chartPane as DependencyObject);

              if (parentChartControl != null)
              {
                 Title lineChartTile = parentChartControl.Titles[0] as Title ;
                 Param rowParam = rowData.Row as Param;
                 string titleContent = lineChartTile.Content as string;
                 if (titleContent == null || "".Equals(titleContent))
                 {
                    lineChartTile.Content = rowParam.paramChineseName + "曲线";
                 }
              }
               
              if (series2D == null && xyDiagram2D != null)
              {
                  series2D = xyDiagram2D.Series[0] as LineSeries2D;
                  timer.Interval = TimeSpan.FromMilliseconds(50);
                  timer.Tick += new EventHandler(RefreshPlot);
                  timer.IsEnabled = true;
              }
            }
            //MessageBox.Show(((Param)rowData.Row).paramName);
        }

        private void RefreshPlot(object sender, EventArgs e)
        {
            if (value > number)
            {
                value = 1;
            }
            else
            {
                value += 2;
            }
            SeriesPoint p = new SeriesPoint(interval, value);
            if (series2D != null)
            {
                series2D.Points.Add(p);
                interval++;
                if (series2D.Points.Count > number)
                {
                    series2D.Points.RemoveAt(0);
                }
            }
        }

       

    }
}
<file_sep>﻿using DevExpress.Mvvm;
using DevExpress.Xpf.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace CardWorkbench.ViewModels.MenuControls
{
    public abstract class MenuControlsViewModel : ViewModelBase
    {
        public ICommand stopLoadingSplashCommand
        {
            get { return new DelegateCommand<object>(onstopLoadingSplashLoaded, x => { return true; }); }
        }

        private void onstopLoadingSplashLoaded(object context)
        {
            DXSplashScreen.Close();
        }
    }
}
<file_sep>﻿
using DevExpress.Mvvm;
using DevExpress.Xpf.Gauges;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace CardWorkbench.ViewModels.CustomControls
{
    public class RFLevelMasterGaugeViewModel : ViewModelBase
    {

        //临时引入一个信号强度计时器
        private DispatcherTimer timer = new DispatcherTimer();

        //信号强度刻度条
        LinearScale linearScale;

        //信号强度进度条命令
        public ICommand masterMcLevelProgressBarCommand
        {
            get { return new DelegateCommand<RoutedEventArgs>(onMasterMcLevelProgressBarLoaded, x => { return true; }); }
        }

        private void onMasterMcLevelProgressBarLoaded(RoutedEventArgs e)
        {
            linearScale = e.Source as LinearScale;
            timer.Interval = TimeSpan.FromMilliseconds(200);
            timer.Tick += new EventHandler(masterLevelRandomChange);
            timer.Start();

        }
        private void masterLevelRandomChange(object sender, EventArgs e)
        {
            Random rnd = new Random();
            double val = rnd.Next(-110, -9); // creates a number between 1 and 12
            linearScale.Ranges[0].EndValue = new RangeValue(val);
        }

    }
}
