| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073 | using Aitex.Core.RT.Log;using Caliburn.Micro;using MECF.Framework.Common.CommonData;using MECF.Framework.Common.DataCenter;using MECF.Framework.UI.Client.CenterViews.Editors;using MECF.Framework.UI.Client.CenterViews.Editors.Recipe;using MECF.Framework.UI.Client.CenterViews.Editors.Sequence;using MECF.Framework.UI.Client.ClientBase;using OpenSEMI.ClientBase;using RecipeEditorLib.RecipeModel.Params;using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Text.RegularExpressions;using System.Windows;using System.Xml;using System.Linq;using System.Windows.Controls;using System.IO;using FurnaceUI.Views.Editors;using System.Threading.Tasks;namespace FurnaceUI.Views.Recipes{    public class RecipesHistoryCompareViewModel : ModuleUiViewModelBase    {        private string _module = "PM1";        public ObservableCollection<ProcessTypeFileItem> ProcessTypeFileList { get; set; }        public ObservableCollection<string> ChamberType { get; set; }        public ObservableCollection<string> RecipeProcessType { get; set; }        public int ChamberTypeIndexSelection { get; set; }        public int _processTypeIndexSelection;        public int ProcessTypeIndexSelection        {            get { return _processTypeIndexSelection; }            set { _processTypeIndexSelection = value; NotifyOfPropertyChange("ProcessTypeIndexSelection"); }        }        public string CurrentChamberType        {            get            {                return ChamberType[ChamberTypeIndexSelection];            }        }        private string _currentProcessType;        public string CurrentProcessType        {            get            {                if (ProcessTypeIndexSelection < 0)                    ProcessTypeIndexSelection = 0;                if (ProcessTypeFileList.Count == 0)                    return "Process";                return ProcessTypeFileList[ProcessTypeIndexSelection].ProcessType;            }            set { _currentProcessType = CurrentProcessType; NotifyOfPropertyChange("CurrentProcessType"); }        }        //-------------------------A Properties        public ObservableCollection<StepDataItem> StepListA { get; set; }        public ObservableCollection<ParamDataItem> ParamListA { get; set; }        public ObservableCollection<LineDataItem> WholeListA { get; set; }        public string RecipeA { get; set; }        public string TimeA        {            get { return _timeA; }            set            {                _timeA = value;                NotifyOfPropertyChange("TimeA");            }        }        private string _timeA = string.Empty;        private XmlDocument _domA = new XmlDocument();        private string _pathPrefixA;        private Dictionary<string, ObservableCollection<ParamDataItem>> _mapStepParamA = new Dictionary<string, ObservableCollection<ParamDataItem>>();        private Dictionary<string, LineDataItem> _mapLineTextA = new Dictionary<string, LineDataItem>();        private List<string> BackInnerXmlTextA = new List<string>();        private bool _isChangedA { get; set; }        public bool EnableButtonRemoveA        {            get { return !string.IsNullOrEmpty(RecipeA); }        }        public bool EnableButtonUndoA        {            get { return false; }        }        public bool EnableButtonSaveA        {            get { return false; }        }        private StepDataItem _stepSelectionA;        public StepDataItem StepSelectionA        {            get            {                return _stepSelectionA;            }            set            {                SyncStepSelection(value, false);                _stepSelectionA = value;            }        }        private ParamDataItem _paramSelectionA;        public ParamDataItem ParamSelectionA        {            get            {                return _paramSelectionA;            }            set            {                SyncParamSelection(value, false);                _paramSelectionA = value;            }        }        private LineDataItem _lineSelectionA;        public LineDataItem LineSelectionA        {            get            {                return _lineSelectionA;            }            set            {                SyncLineSelection(value, false);                _lineSelectionA = value;            }        }        //-------------------------B Properties-------------------------------------------------------------        public ObservableCollection<StepDataItem> StepListB { get; set; }        public ObservableCollection<ParamDataItem> ParamListB { get; set; }        public ObservableCollection<LineDataItem> WholeListB { get; set; }        public string RecipeB { get; set; }        public string TimeB        {            get { return _timeB; }            set            {                _timeB = value;                NotifyOfPropertyChange("TimeB");            }        }        private string _timeB = string.Empty;        private XmlDocument _domB = new XmlDocument();        private string _pathPrefixB;        private Dictionary<string, ObservableCollection<ParamDataItem>> _mapStepParamB = new Dictionary<string, ObservableCollection<ParamDataItem>>();        private Dictionary<string, LineDataItem> _mapLineTextB = new Dictionary<string, LineDataItem>();        private List<string> BackInnerXmlTextB = new List<string>();        private string BaseTextB = "";        private bool _isChangedB { get; set; }        public bool EnableButtonRemoveB        {            get { return !string.IsNullOrEmpty(RecipeB); }        }        public bool EnableButtonUndoB        {            get { return false; }        }        public bool EnableButtonSaveB        {            get { return false; }        }        private StepDataItem _stepSelectionB;        public StepDataItem StepSelectionB        {            get            {                return _stepSelectionB;            }            set            {                SyncStepSelection(value, true);                _stepSelectionB = value;            }        }        private ParamDataItem _paramSelectionB;        public ParamDataItem ParamSelectionB        {            get            {                return _paramSelectionB;            }            set            {                SyncParamSelection(value, true);                _paramSelectionB = value;            }        }        private LineDataItem _lineSelectionB;        public LineDataItem LineSelectionB        {            get            {                return _lineSelectionB;            }            set            {                SyncLineSelection(value, true);                _lineSelectionB = value;            }        }        private ShowRecipeHistory recipeHistory;        public ShowRecipeHistory RecipeHistory        {            get => recipeHistory;            set            {                recipeHistory = value;                if (recipeHistory != null)                {                    RecipeB = recipeHistory.Recipe_Name;                    TimeB = recipeHistory.LastRevisionTime.ToString("yyyy-MM-dd HH:mm:ss");                }                              NotifyOfPropertyChange("RecipeHistory");            }        }        private RecipeDataBase currentRecipe;        public RecipeDataBase CurrentRecipe        {            get => currentRecipe;            set            {                currentRecipe = value;                if (currentRecipe!=null)                {                    RecipeA = currentRecipe.Name;                    TimeA = currentRecipe.ReviseTime.ToString("yyyy-MM-dd HH:mm:ss");                }                            NotifyOfPropertyChange("CurrentRecipe");            }        }        public bool CurrentRecipeIsHistoty { get; set; }        private ShowRecipeHistory _currentRecipeHistory;        public ShowRecipeHistory CurrentRecipeHistory        {            get => _currentRecipeHistory;            set            {                _currentRecipeHistory = value;                if (_currentRecipeHistory != null)                {                    RecipeA = _currentRecipeHistory.Recipe_Name;                    TimeA = _currentRecipeHistory.LastRevisionTime.ToString("yyyy-MM-dd HH:mm:ss");                }                NotifyOfPropertyChange("CurrentRecipeHistory");            }        }        public RecipesHistoryCompareViewModel()        {            StepListA = new ObservableCollection<StepDataItem>();            ParamListA = new ObservableCollection<ParamDataItem>();            WholeListA = new ObservableCollection<LineDataItem>();            StepListB = new ObservableCollection<StepDataItem>();            ParamListB = new ObservableCollection<ParamDataItem>();            WholeListB = new ObservableCollection<LineDataItem>();        }        protected override void OnInitialize()        {            base.OnInitialize();            var chamberType = QueryDataClient.Instance.Service.GetConfig("System.Recipe.SupportedChamberType");            if (chamberType == null)            {                ChamberType = new ObservableCollection<string>() { "Default" };            }            else            {                ChamberType = new ObservableCollection<string>(((string)(chamberType)).Split(','));            }            ChamberTypeIndexSelection = 0;            //Etch:Process,Clean,Chuck,Dechuck;CVD:Process,Clean;            var processType = QueryDataClient.Instance.Service.GetConfig("System.Recipe.SupportedProcessType");            if (processType == null)            {                RecipeProcessType = new ObservableCollection<string>() { "Process" };            }            else            {                RecipeProcessType = new ObservableCollection<string>(((string)processType).Split(','));            }            ProcessTypeFileList = new ObservableCollection<ProcessTypeFileItem>();            var chamber = QueryDataClient.Instance.Service.GetConfig("System.Recipe.ChamberModules");            UpdateProcessTypeFileList();        }        protected override void OnActivate()        {            base.OnActivate();            SelectRecipe();            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);        }        protected override void OnDeactivate(bool close)        {            base.OnDeactivate(close);        }        public void UpdateProcessTypeFileList()        {            ProcessTypeFileList.Clear();            for (int i = 0; i < RecipeProcessType.Count; i++)            {                var type = new ProcessTypeFileItem();                type.ProcessType = RecipeProcessType[i];                var prefix = $"{ChamberType[ChamberTypeIndexSelection]}\\{RecipeProcessType[i]}";                ProcessTypeFileList.Add(type);            }            while (ProcessTypeFileList.Count > RecipeProcessType.Count)            {                ProcessTypeFileList.RemoveAt(0);            }        }        private void SelectRecipe()        {            try            {                var recipeProvider = new RecipeProvider();                string suffix = $".{_module}";                if (RecipeHistory != null)                {                    LoadContentData(RecipeHistory);                }                if (CurrentRecipeIsHistoty)                {                    if (CurrentRecipeHistory != null)                    {                        LoadCurrentHistoryContentData(CurrentRecipeHistory);                    }                }                else                {                    if (CurrentRecipe != null)                    {                        LoadData(CurrentRecipe);                    }                }                Recompare();                SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);            }            catch (Exception ex)            {                throw;            }        }        /// <summary>        /// 当前版本显示在左边        /// </summary>        /// <param name="selectedRecipePath"></param>        public void LoadData(RecipeDataBase Recipe)        {            string recipeName = Recipe.Name;            string prefixPath = Recipe.PrefixPath;            var _recipeProvider = new RecipeProvider();            var recipeContent = _recipeProvider.LoadRecipe(prefixPath, recipeName, false);//_recipeProvider.LoadRecipeByFullPath(selectedRecipePath);//             if (string.IsNullOrEmpty(recipeContent))            {                MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid.");                return;            }            BackInnerXmlTextA.Clear();            if (BackInnerXmlTextB.Count > 0)            {                string dataXml = BackInnerXmlTextB[0];                BackInnerXmlTextB.Clear();                BackInnerXmlTextB.Add(dataXml);            }            _pathPrefixA = prefixPath;            _mapLineTextA = new Dictionary<string, LineDataItem>();            BackInnerXmlTextA.Add(recipeContent);            LoadrecipeContentData(recipeContent, true);        }        /// <summary>        /// 当前历史版本显示在左边        /// </summary>        /// <param name="recipeHistory"></param>        public void LoadCurrentHistoryContentData(ShowRecipeHistory recipeHistory)        {            string recipeName = recipeHistory.Recipe_Name;            string prefixPath = recipeHistory.Recipe_Type;            var _recipeProvider = new RecipeProvider();            var recipeContent = recipeHistory.Recipe_Content;//_recipeProvider.LoadRecipe(prefixPath, recipeName, false);// _recipeProvider.LoadRecipeByFullPath(selectedRecipePath);//             if (string.IsNullOrEmpty(recipeContent))            {                MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid.");                return;            }            BackInnerXmlTextA.Clear();            if (BackInnerXmlTextB.Count > 0)            {                string dataXml = BackInnerXmlTextB[0];                BackInnerXmlTextB.Clear();                BackInnerXmlTextB.Add(dataXml);            }            _pathPrefixA = prefixPath;            _mapLineTextA = new Dictionary<string, LineDataItem>();            BackInnerXmlTextA.Add(recipeContent);            LoadrecipeContentData(recipeContent, true);        }        /// <summary>        /// 历史版本显示在右边        /// </summary>        /// <param name="recipeHistory"></param>        public void LoadContentData(ShowRecipeHistory recipeHistory)        {            XmlDocument doc = _domB;            string recipeName = recipeHistory.Recipe_Name;            string prefixPath = recipeHistory.Recipe_Type;            var _recipeProvider = new RecipeProvider();            var recipeContent = recipeHistory.Recipe_Content;//_recipeProvider.LoadRecipe(prefixPath, recipeName, false);// _recipeProvider.LoadRecipeByFullPath(selectedRecipePath);//             if (string.IsNullOrEmpty(recipeContent))            {                MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid.");                return;            }            BackInnerXmlTextB.Clear();            if (BackInnerXmlTextA.Count > 0)            {                string dataXml = BackInnerXmlTextA[0];                BackInnerXmlTextA.Clear();                BackInnerXmlTextA.Add(dataXml);            }            _pathPrefixB = prefixPath;            _mapLineTextB = new Dictionary<string, LineDataItem>();            BackInnerXmlTextB.Add(recipeContent);            LoadrecipeContentData(recipeContent, false);            // LoadrecipeContentDataB(recipeContent);        }        //private void SelectRecipe(bool isSelectA)        //{        //    try        //    {        //        RecipeCompareSelectDialogViewModel dialog = new RecipeCompareSelectDialogViewModel();        //        dialog.DisplayName = "Select Recipe";        //        SystemName = _module;        //        var recipeProvider = new RecipeProvider();        //        var processType = QueryDataClient.Instance.Service.GetConfig("System.Recipe.SupportedProcessType");        //        if (processType == null)        //        {        //            processType = "Process";        //        }        //        var ProcessTypeFileList = new ObservableCollection<ProcessTypeFileItem>();        //        string[] recipeProcessType = ((string)processType).Split(',');        //        string[] partsType1 = new string[] { };        //        string[] partsType2 = new string[] { };        //        for (int i = 0; i < recipeProcessType.Length; i++)        //        {        //            var type = new ProcessTypeFileItem();        //            type.ProcessType = recipeProcessType[i];        //            var prefix = $"ISSET\\{recipeProcessType[i]}";        //            var recipes = recipeProvider.GetXmlRecipeList(prefix);        //            string[] parts = Regex.Split(recipes, "<");        //            if (i == 0)        //            {        //                partsType1 = parts;        //            }        //            else if (i == 1)        //            {        //                partsType2 = parts;        //            }        //            string recipeChamber;        //            recipeChamber = "<" + parts[1];        //            foreach (string part in parts)        //            {        //                if (part.Contains($".{SystemName}"))        //                {        //                    string temp = part.Replace($".{SystemName}", string.Empty);        //                    recipeChamber += "<" + temp;        //                }        //            }        //            if (parts.Length > 2)        //            {        //                recipeChamber += "<" + parts[parts.Length - 1];        //            }        //            type.FileListByProcessType = RecipeSequenceTreeBuilder.BuildFileNode(prefix, "", false, recipeChamber)[0].Files;        //            ProcessTypeFileList.Add(type);        //        }        //        dialog.ProcessTypeFileList = ProcessTypeFileList;        //        WindowManager wm = new WindowManager();        //        bool? bret = wm.ShowDialog(dialog);        //        if (!(bool)bret)        //            return;        //        _module = dialog.SelectedChamber;        //        string suffix = $".{_module}";        //        string dialogResult = dialog.DialogResult;        //        bool isFullPath = false;        //        if (dialogResult.Contains(".rcp"))        //            isFullPath = true;        //        string recipeName = dialogResult;        //        if (isSelectA)        //        {        //            RecipeA = recipeName;        //            NotifyOfPropertyChange(nameof(RecipeA));        //            NotifyOfPropertyChange(nameof(EnableButtonRemoveA));        //        }        //        else        //        {        //            RecipeB = recipeName;        //            NotifyOfPropertyChange(nameof(RecipeB));        //            NotifyOfPropertyChange(nameof(EnableButtonRemoveB));        //        }        //        if (!string.IsNullOrEmpty(RecipeA) && !string.IsNullOrEmpty(RecipeB))        //        {        //            string[] recipe1 = RecipeA.Split('\\'); string r1 = recipe1[0];        //            string[] recipe2 = RecipeB.Split('\\'); string r2 = recipe2[0];        //            if (r1 != r2)        //            {        //                if (MessageBoxResult.Yes != MessageBox.Show($"腔体类型不一致! \n 是否继续比较 ?", "", MessageBoxButton.YesNo, MessageBoxImage.Information))        //                {        //                    RemoveSelectB();        //                    return;        //                }        //            }        //        }        //        LoadData(recipeName, isSelectA, isFullPath);        //        Recompare();        //        SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);        //    }        //    catch (Exception ex)        //    {        //        throw;        //    }        //}        public void LoadData(string selectedRecipePath, bool isSelectA, bool isFullPath)        {            var array = selectedRecipePath.Split(new char[] { '\\' });            string recipeName = array[array.Length - 1];            XmlDocument doc = isSelectA ? _domA : _domB;            string prefixPath = (isSelectA ? RecipeA : RecipeB).Replace(recipeName, "");            var _recipeProvider = new RecipeProvider();            var recipeContent = isFullPath ? _recipeProvider.LoadRecipeByFullPath(selectedRecipePath) : _recipeProvider.LoadRecipe(prefixPath, recipeName, false);            if (string.IsNullOrEmpty(recipeContent))            {                MessageBox.Show($"{prefixPath}\\{recipeName} is empty, please confirm the file is valid.");                return;            }            if (isSelectA)            {                BackInnerXmlTextA.Clear();                if (BackInnerXmlTextB.Count > 0)                {                    string dataXml = BackInnerXmlTextB[0];                    BackInnerXmlTextB.Clear();                    BackInnerXmlTextB.Add(dataXml);                }            }            else            {                BackInnerXmlTextB.Clear();                if (BackInnerXmlTextA.Count > 0)                {                    string dataXml = BackInnerXmlTextA[0];                    BackInnerXmlTextA.Clear();                    BackInnerXmlTextA.Add(dataXml);                }            }            if (isSelectA)            {                _pathPrefixA = prefixPath;                _mapLineTextA = new Dictionary<string, LineDataItem>();                BackInnerXmlTextA.Add(recipeContent);            }            else            {                _pathPrefixB = prefixPath;                _mapLineTextB = new Dictionary<string, LineDataItem>();                BackInnerXmlTextB.Add(recipeContent);            }            LoadrecipeContentData(recipeContent, isSelectA);        }        public void StepGridSelectionChangedA()        {            if (StepSelectionA == null)            {                ParamListA.Clear();                NotifyOfPropertyChange(nameof(ParamListA));                return;            }            Task.Run(() =>                 {                     if (_mapStepParamA.ContainsKey(StepSelectionA.StepNumber))                     {                         // ParamListA = _mapStepParamA[StepSelectionA.StepNumber];                         var tempParamListA = _mapStepParamA[StepSelectionA.StepNumber];                         foreach (ParamDataItem item in tempParamListA)                         {                             item.IsHidden = (!item.IsDiff && !item.IsExtra && IsShowDiffParams) ? true : false;                         }                         Application.Current.Dispatcher.Invoke(new System.Action(() =>                         {                             ParamListA.Clear();                             tempParamListA.ToList().ForEach(x => ParamListA.Add(x));                         }));                         NotifyOfPropertyChange(nameof(ParamListA));                         NotifyOfPropertyChange(nameof(StepSelectionA));                         //StepSelectionA.InvokePropertyChanged();                     }                 });        }        public void LoadDataByRecipeContent(string recipeContent, bool isSelectA)        {            LoadrecipeContentData(recipeContent, isSelectA);        }        private void LoadrecipeContentData(string recipeContent, bool isSelectA)        {            XmlDocument doc = isSelectA ? _domA : _domB;            if (isSelectA)            {                _mapLineTextA = new Dictionary<string, LineDataItem>();                //BackInnerXmlTextA.Add(recipeContent);            }            else            {                _mapLineTextB = new Dictionary<string, LineDataItem>();                //BackInnerXmlTextB.Add(recipeContent);            }            if (!isSelectA)            {                doc.LoadXml(recipeContent);                StringWriter stringWriter = new StringWriter();                XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);                xmlTextWriter.Formatting = Formatting.Indented;                doc.WriteTo(xmlTextWriter);                recipeContent = stringWriter.ToString();            }            string[] allText = recipeContent.Split(new string[] { "\r\n" }, StringSplitOptions.None);            int number = 0;            ObservableCollection<LineDataItem> lineData = new ObservableCollection<LineDataItem>();            foreach (string lineText in allText)            {                LineDataItem line = new LineDataItem();                line.LineNumber = (++number).ToString();                line.LineText = lineText;                if (!string.IsNullOrEmpty(lineText))                {                    lineData.Add(line);                    if (isSelectA)                    {                        _mapLineTextA[line.LineNumber] = line;                    }                    else                    {                        _mapLineTextB[line.LineNumber] = line;                    }                }            }            doc.LoadXml(recipeContent);            ObservableCollection<StepDataItem> stepData = new ObservableCollection<StepDataItem>();            XmlNodeList nodeSteps = doc.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/Step");            if (nodeSteps == null)                nodeSteps = doc.SelectNodes($"Aitex/TableRecipeData/Step");            foreach (XmlNode nodeStep in nodeSteps)            {                ObservableCollection<ParamDataItem> paramData = new ObservableCollection<ParamDataItem>();                StepDataItem step = new StepDataItem();                foreach (XmlAttribute attr in nodeStep.Attributes)                {                    if (attr.Name == "StepNo")                        step.StepNumber = attr.Value;                    else if (attr.Name == "Name")                        step.StepName = attr.Value;                    else                    {                        ParamDataItem param = new ParamDataItem();                        param.ParamName = attr.Name;                        param.ParamValue = attr.Value;                        paramData.Add(param);                    }                }                stepData.Add(step);                if (isSelectA)                {                    _mapStepParamA[step.StepNumber] = paramData;                }                else                {                    _mapStepParamB[step.StepNumber] = paramData;                }            }            if (isSelectA)            {                StepListA = stepData;                NotifyOfPropertyChange(nameof(StepListA));                WholeListA = lineData;                NotifyOfPropertyChange(nameof(WholeListA));            }            else            {                StepListB = stepData;                NotifyOfPropertyChange(nameof(StepListB));                WholeListB = lineData;                NotifyOfPropertyChange(nameof(WholeListB));            }        }        public void StepGridSelectionChangedB()        {            if (StepSelectionB == null)            {                ParamListB.Clear();                NotifyOfPropertyChange(nameof(ParamListB));                return;            }            if (_mapStepParamB.ContainsKey(StepSelectionB.StepNumber))            {                // ParamListB = _mapStepParamB[StepSelectionB.StepNumber];                var tempParamListB = _mapStepParamB[StepSelectionB.StepNumber];                foreach (ParamDataItem item in tempParamListB)                {                    item.IsHidden = (!item.IsDiff && !item.IsExtra && IsShowDiffParams) ? true : false;                }                Application.Current.Dispatcher.Invoke(new System.Action(() =>                {                    ParamListB.Clear();                    tempParamListB.ToList().ForEach(x => ParamListB.Add(x));                }                ));                NotifyOfPropertyChange(nameof(ParamListB));                NotifyOfPropertyChange(nameof(StepSelectionB));                // StepSelectionB.InvokePropertyChanged();            }        }        public void ParamGridSelectionChangedA()        {            if (ParamSelectionA == null)            {                return;            }            NotifyOfPropertyChange(nameof(ParamSelectionA));            ParamSelectionA.InvokePropertyChanged();        }        public void ParamGridSelectionChangedB()        {            if (ParamSelectionB == null)            {                return;            }            NotifyOfPropertyChange(nameof(ParamSelectionB));            ParamSelectionB.InvokePropertyChanged();        }        public void WholeGridSelectionChangedA()        {            if (LineSelectionA == null)            {                return;            }            NotifyOfPropertyChange(nameof(LineSelectionA));            LineSelectionA.InvokePropertyChanged();        }        public void WholeGridSelectionChangedB()        {            if (LineSelectionB == null)            {                return;            }            NotifyOfPropertyChange(nameof(LineSelectionB));            LineSelectionB.InvokePropertyChanged();        }        public void SaveLineA()        {            if (LineSelectionA == null)                return;            foreach (LineDataItem lineDataItem in WholeListA)            {                if (lineDataItem.LineNumber == LineSelectionA.LineNumber)                {                    lineDataItem.LineText = LineSelectionA.LineText;                    break;                }            }            string recipeContent = "";            for (int i = 0; i < WholeListA.Count; i++)            {                recipeContent += WholeListA[i].LineText + ((i == WholeListB.Count - 1) ? "" : "\r\n");            }            CopyToInnerXml(recipeContent, true);            LoadDataByRecipeContent(recipeContent, true);            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);        }        public void SaveLineB()        {            if (LineSelectionB == null)                return;            foreach (LineDataItem lineDataItem in WholeListB)            {                if (lineDataItem.LineNumber == LineSelectionB.LineNumber)                {                    lineDataItem.LineText = LineSelectionB.LineText;                    break;                }            }            string recipeContent = "";            for (int i = 0; i < WholeListB.Count; i++)            {                recipeContent += WholeListB[i].LineText + ((i == WholeListB.Count - 1) ? "" : "\r\n");            }            CopyToInnerXml(recipeContent, false);            LoadDataByRecipeContent(recipeContent, false);            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);        }        private void Recompare()        {            RecompareStep();            RecompareWhole();        }        private void RecompareStep()        {            if (StepListA == null || StepListB == null)                return;            int i = 0;            for (i = 0; i < StepListA.Count && i < StepListB.Count; i++)            {                if (StepListA[i].StepName == StepListB[i].StepName)                    StepListA[i].IsDiffName = StepListB[i].IsDiffName = false;                else                    StepListA[i].IsDiffName = StepListB[i].IsDiffName = true;                ObservableCollection<ParamDataItem> paramA = _mapStepParamA[StepListA[i].StepNumber];                ObservableCollection<ParamDataItem> paramB = _mapStepParamB[StepListB[i].StepNumber];                bool isDiff = false;                bool IsExtra = true;                foreach (var pa in paramA)                {                    pa.IsExtra = true;                }                foreach (var pb in paramB)                {                    pb.IsExtra = true;                }                foreach (var pa in paramA)                {                    foreach (var pb in paramB)                    {                        if (pb.ParamName == pa.ParamName)                        {                            pb.IsExtra = false;                            pa.IsExtra = false;                            pb.IsDiff = pa.IsDiff = (pa.ParamValue != pb.ParamValue);                            if (pa.IsDiff)                                isDiff = true;                            break;                        }                    }                }                foreach (var pa in paramA)                {                    pa.InvokePropertyChanged();                }                foreach (var pb in paramB)                {                    pb.InvokePropertyChanged();                }                StepListA[i].IsDiff = StepListB[i].IsDiff = isDiff;                StepListA[i].IsExtra = StepListB[i].IsExtra = false;                StepListA[i].IsHidden = StepListB[i].IsHidden = !isDiff && IsShowDiffSteps ? true : false;                StepListA[i].InvokePropertyChanged();                StepListB[i].InvokePropertyChanged();            }            for (int j = i; j < StepListA.Count; j++)            {                StepListA[j].IsDiff = false;                StepListA[j].IsExtra = true;                StepListA[j].InvokePropertyChanged();                foreach (var pa in _mapStepParamA[StepListA[j].StepNumber])                {                    pa.InvokePropertyChanged();                }            }            for (int k = i; k < StepListB.Count; k++)            {                StepListB[k].IsDiff = false;                StepListB[k].IsExtra = true;                WholeListB[k].InvokePropertyChanged();                _mapLineTextB[WholeListB[k].LineNumber].InvokePropertyChanged();                foreach (var pb in _mapStepParamB[StepListB[k].StepNumber])                {                    pb.InvokePropertyChanged();                }            }            NotifyOfPropertyChange(nameof(StepListA));            NotifyOfPropertyChange(nameof(StepListB));        }        private void RecompareWhole()        {            if (WholeListA == null || WholeListB == null)                return;            int i = 0;            for (i = 0; i < WholeListA.Count && i < WholeListB.Count; i++)            {                LineDataItem lineA = _mapLineTextA[WholeListA[i].LineNumber];                LineDataItem lineB = _mapLineTextB[WholeListB[i].LineNumber];                bool isDiff = false;                lineB.IsDiff = lineA.IsDiff = (lineA.LineText != lineB.LineText);                if (lineA.IsDiff)                    isDiff = true;                WholeListA[i].IsDiff = WholeListB[i].IsDiff = isDiff;                WholeListA[i].IsExtra = WholeListB[i].IsExtra = false;                _mapLineTextA[WholeListA[i].LineNumber].IsDiff = _mapLineTextB[WholeListB[i].LineNumber].IsDiff = isDiff;                _mapLineTextA[WholeListA[i].LineNumber].IsExtra = _mapLineTextB[WholeListB[i].LineNumber].IsExtra = false;                lineA.InvokePropertyChanged();                lineB.InvokePropertyChanged();                WholeListA[i].InvokePropertyChanged();                WholeListB[i].InvokePropertyChanged();            }            for (int j = i; j < WholeListA.Count; j++)            {                WholeListA[j].IsDiff = false;                WholeListA[j].IsExtra = true;                _mapLineTextA[WholeListA[j].LineNumber].IsDiff = false;                _mapLineTextA[WholeListA[j].LineNumber].IsExtra = true;                if (!(_mapLineTextA[WholeListA[j].LineNumber].LineText.Contains("<Step StepNo") || _mapLineTextA[WholeListA[j].LineNumber].LineText.Contains("<Moudule Name")))                {                    WholeListA[j].IsDiff = false;                    WholeListA[j].IsExtra = false;                }                WholeListA[j].InvokePropertyChanged();                _mapLineTextA[WholeListA[j].LineNumber].InvokePropertyChanged();            }            for (int k = i; k < WholeListB.Count; k++)            {                WholeListB[k].IsDiff = false;                WholeListB[k].IsExtra = true;                _mapLineTextB[WholeListB[k].LineNumber].IsDiff = false;                _mapLineTextB[WholeListB[k].LineNumber].IsExtra = true;                if (!(_mapLineTextB[WholeListB[k].LineNumber].LineText.Contains("<Step StepNo") || _mapLineTextB[WholeListB[k].LineNumber].LineText.Contains("<Moudule Name")))                {                    WholeListB[k].IsDiff = false;                    WholeListB[k].IsExtra = false;                }                WholeListB[k].InvokePropertyChanged();                _mapLineTextB[WholeListB[k].LineNumber].InvokePropertyChanged();            }            NotifyOfPropertyChange(nameof(WholeListA));            NotifyOfPropertyChange(nameof(WholeListB));        }        private void SyncStepSelection(StepDataItem stepData, bool isSelectA)        {            if (stepData == null)                return;            if (isSelectA)            {                var findStepA = StepListA.FirstOrDefault(x => x.StepNumber == stepData.StepNumber);                if (findStepA != null)                {                    _stepSelectionA = findStepA;                    NotifyOfPropertyChange(nameof(StepSelectionA));                    StepSelectionA.InvokePropertyChanged();                }            }            else            {                var findStepB = StepListB.FirstOrDefault(x => x.StepNumber == stepData.StepNumber);                if (findStepB != null)                {                    _stepSelectionB = findStepB;                    NotifyOfPropertyChange(nameof(StepSelectionB));                    StepSelectionB.InvokePropertyChanged();                }            }        }        private void SyncParamSelection(ParamDataItem paramData, bool isSelectA)        {            try            {                if (paramData == null)                    return;                if (isSelectA)                {                    if (_mapStepParamA.ContainsKey(StepSelectionB.StepNumber))                    {                        ParamListA = _mapStepParamA[StepSelectionB.StepNumber];                        NotifyOfPropertyChange(nameof(ParamListA));                    }                    else                        return;                    foreach (var item in ParamListA)                    {                        if (item.ParamName == paramData.ParamName)                        {                            _paramSelectionA = item;                            NotifyOfPropertyChange(nameof(ParamSelectionA));                            ParamSelectionA.InvokePropertyChanged();                        }                    }                }                else                {                    if (ParamListB == null)                    {                        if (_mapStepParamB.ContainsKey(StepSelectionA.StepNumber))                        {                            ParamListB = _mapStepParamB[StepSelectionA.StepNumber];                            NotifyOfPropertyChange(nameof(ParamListB));                        }                        else                            return;                    }                    foreach (var item in ParamListB)                    {                        if (item.ParamName == paramData.ParamName)                        {                            _paramSelectionB = item;                            NotifyOfPropertyChange(nameof(ParamSelectionB));                            ParamSelectionB.InvokePropertyChanged();                        }                    }                }            }            catch (Exception ex)            {                LOG.Write(ex.Message);            }        }        private void SyncLineSelection(LineDataItem lineData, bool isSelectA)        {            if (lineData == null)                return;            if (isSelectA)            {                foreach (var item in WholeListA)                {                    if (item.LineNumber == lineData.LineNumber)                    {                        _lineSelectionA = item;                        NotifyOfPropertyChange(nameof(LineSelectionA));                        LineSelectionA.InvokePropertyChanged();                    }                }            }            else            {                foreach (var item in WholeListB)                {                    if (item.LineNumber == lineData.LineNumber)                    {                        _lineSelectionB = item;                        NotifyOfPropertyChange(nameof(LineSelectionB));                        LineSelectionB.InvokePropertyChanged();                    }                }            }        }        public void RemoveA()        {            RemoveRecipe(true);        }        public void RemoveB()        {            RemoveRecipe(false);        }        private void RemoveSelectB()        {            StepListB?.Clear();            ParamListB?.Clear();            WholeListB?.Clear();            RecipeB = string.Empty;            _mapStepParamB?.Clear();            _stepSelectionB = null;            _paramSelectionB = null;            NotifyOfPropertyChange(nameof(StepListB));            NotifyOfPropertyChange(nameof(ParamListB));            NotifyOfPropertyChange(nameof(RecipeB));            NotifyOfPropertyChange(nameof(EnableButtonRemoveB));            NotifyOfPropertyChange(nameof(StepSelectionB));            NotifyOfPropertyChange(nameof(ParamSelectionB));        }        private void RemoveRecipe(bool isSelectA)        {            if (!DialogBox.Confirm($"Are you sure you want to remove the recipe? \r\n{RecipeB}"))                return;            if (isSelectA)            {                StepListA?.Clear();                ParamListA?.Clear();                WholeListA?.Clear();                RecipeA = string.Empty;                TimeA = string.Empty;                _mapStepParamA?.Clear();                _stepSelectionA = null;                _paramSelectionA = null;                NotifyOfPropertyChange(nameof(StepListA));                NotifyOfPropertyChange(nameof(ParamListA));                NotifyOfPropertyChange(nameof(RecipeA));                NotifyOfPropertyChange(nameof(EnableButtonRemoveA));                NotifyOfPropertyChange(nameof(StepSelectionA));                NotifyOfPropertyChange(nameof(ParamSelectionA));            }            else            {                StepListB?.Clear();                ParamListB?.Clear();                WholeListB?.Clear();                RecipeB = string.Empty;                TimeB = string.Empty;                _mapStepParamB?.Clear();                _stepSelectionB = null;                _paramSelectionB = null;                NotifyOfPropertyChange(nameof(StepListB));                NotifyOfPropertyChange(nameof(ParamListB));                NotifyOfPropertyChange(nameof(RecipeB));                NotifyOfPropertyChange(nameof(EnableButtonRemoveB));                NotifyOfPropertyChange(nameof(StepSelectionB));                NotifyOfPropertyChange(nameof(ParamSelectionB));            }        }        public void StepCopyToRight(StepDataItem stepA)        {            string temp = "";            if (StepSelectionA != null)                temp = StepSelectionA.StepNumber;            StepCopy(stepA, true);            if (!string.IsNullOrEmpty(temp))            {                foreach (StepDataItem tempStep in StepListA)                {                    if (tempStep.StepNumber == temp)                    {                        StepSelectionA = tempStep;                        break;                    }                }            }        }        public void StepCopyToLeft(StepDataItem stepB)        {            string temp = "";            if (StepSelectionB != null)                temp = StepSelectionB.StepNumber;            StepCopy(stepB, false);            if (!string.IsNullOrEmpty(temp))            {                foreach (StepDataItem tempStep in StepListB)                {                    if (tempStep.StepNumber == temp)                    {                        StepSelectionB = tempStep;                        break;                    }                }            }        }        public void LeftDelete(StepDataItem step)        {            StepDelete(step, true);        }        public void RightDelete(StepDataItem step)        {            StepDelete(step, false);        }        private void StepDelete(StepDataItem step, bool isSelectA)        {            ObservableCollection<StepDataItem> stepList = isSelectA ? StepListA : StepListB;            Dictionary<string, ObservableCollection<ParamDataItem>> _mapStepParam = isSelectA ? _mapStepParamA : _mapStepParamB;            foreach (var stepTemp in stepList)            {                if (step.StepNumber != stepTemp.StepNumber)                    continue;                stepList.Remove(stepTemp);                break;            }            for (int i = 0; i < stepList.Count; i++)            {                if (stepList[i].StepNumber != (i + 1).ToString())                {                    if (_mapStepParam.ContainsKey((i + 1).ToString()))                    {                        _mapStepParam[(i + 1).ToString()] = _mapStepParam[stepList[i].StepNumber];                    }                    stepList[i].StepNumber = (i + 1).ToString();                }            }            DeleteInnerXml(isSelectA);            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);        }        private void DeleteInnerXml(bool isSelectA)        {            try            {                XmlDocument docTo = isSelectA ? _domA : _domB;                //XmlNode nodeModule = docTo.SelectSingleNode($"Aitex/TableRecipeData/Module[@Name='{_module}']");                XmlNodeList nodeSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/Step");                if (nodeSteps == null)                    nodeSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Step");                List<XmlNode> oldNodeSteps = new List<XmlNode>();                foreach (XmlNode nodeTemp in nodeSteps)                {                    oldNodeSteps.Add(nodeTemp.Clone());                }                XmlNodeList backSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/BakeStep");                if (backSteps == null)                    backSteps = docTo.SelectNodes($"Aitex/TableRecipeData/BakeStep");                List<XmlNode> oldBackNodeSteps = new List<XmlNode>();                foreach (XmlNode nodeTemp in backSteps)                {                    oldBackNodeSteps.Add(nodeTemp.Clone());                }                XmlNode stepsNode = docTo.SelectSingleNode($"Aitex/TableRecipeData/Module[@Name='{_module}']/Step").ParentNode;                stepsNode.RemoveAll();                (stepsNode as XmlElement).SetAttribute("Name", _module);                ObservableCollection<StepDataItem> stepListTo = isSelectA ? StepListA : StepListB;                if (stepsNode == null)                {                    return;                }                int stepNoCount = 1;                foreach (StepDataItem item in stepListTo)                {                    XmlElement DeviceTree = docTo.CreateElement("Step");                    DeviceTree.SetAttribute("StepNo", (stepNoCount++).ToString());                    DeviceTree.SetAttribute("Name", item.StepName);                    stepsNode.AppendChild(DeviceTree);                }                foreach (XmlNode nodeStep in stepsNode)                {                    string stepNumber = nodeStep.Attributes["StepNo"].Value;                    ObservableCollection<ParamDataItem> paramList =                        isSelectA ? _mapStepParamA[stepNumber] : _mapStepParamB[stepNumber];                    foreach (var param in paramList)                    {                        (nodeStep as XmlElement).SetAttribute(param.ParamName, param.ParamValue);                    }                }                foreach (XmlNode nodeStep in backSteps)                {                    stepsNode.AppendChild(nodeStep);                }                string backText = getXmlText(isSelectA ? _domA : _domB);                LoadDataByRecipeContent(backText, isSelectA);                Recompare();                SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);                if (isSelectA)                {                    BackInnerXmlTextA.Add(backText);                }                else                {                    BackInnerXmlTextB.Add(backText);                }            }            catch (Exception ex)            {                LOG.Write(ex.Message);            }        }        private void StepCopy(StepDataItem stepData, bool isFromA)        {            StepDataItem stepFrom = stepData;            ObservableCollection<StepDataItem> stepListTo = isFromA ? StepListB : StepListA;            Dictionary<string, ObservableCollection<ParamDataItem>> mapFrom = isFromA ? _mapStepParamA : _mapStepParamB;            Dictionary<string, ObservableCollection<ParamDataItem>> mapTo = isFromA ? _mapStepParamB : _mapStepParamA;            bool isNotOverOf = false;            foreach (var stepTo in stepListTo)            {                if (stepTo.StepNumber != stepFrom.StepNumber)                    continue;                isNotOverOf = true;                stepTo.StepName = stepFrom.StepName;                //stepTo.IsDiff = stepFrom.IsDiff = false;                //stepTo.IsExtra = stepFrom.IsExtra = false;                if (mapFrom.ContainsKey(stepFrom.StepNumber) &&                    mapTo.ContainsKey(stepTo.StepNumber))                {                    foreach (var paramFrom in mapFrom[stepFrom.StepNumber])                    {                        foreach (var paramTo in mapTo[stepFrom.StepNumber])                        {                            if (paramTo.ParamName != paramFrom.ParamName)                                continue;                            paramTo.ParamValue = paramFrom.ParamValue;                            break;                        }                    }                }                break;            }            if (!isNotOverOf)            {                StepDataItem stepDataItem = new StepDataItem();                stepDataItem.StepName = stepFrom.StepName;                stepDataItem.StepNumber = (stepListTo.Count + 1).ToString();                stepListTo.Add(stepDataItem);                ObservableCollection<ParamDataItem> paramDataItems = new ObservableCollection<ParamDataItem>();                foreach (var paramFrom in mapFrom[stepFrom.StepNumber])                {                    ParamDataItem paramDataItem = new ParamDataItem();                    paramDataItem.ParamName = paramFrom.ParamName;                    paramDataItem.ParamValue = paramFrom.ParamValue;                    paramDataItems.Add(paramDataItem);                }                if (mapTo.ContainsKey(stepDataItem.StepNumber))                    mapTo[stepDataItem.StepNumber] = paramDataItems;                else                    mapTo.Add(stepDataItem.StepNumber, paramDataItems);            }            CopyToInnerXml(!isFromA);            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);            SyncStepSelection(stepFrom, !isFromA);        }        private void CopyToInnerXml(bool isSelectA)        {            try            {                XmlDocument docTo = isSelectA ? _domA : _domB;                XmlNode nodeModule = docTo.SelectSingleNode($"Aitex/TableRecipeData/Module[@Name='{_module}']");                XmlNodeList nodeSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/Step");                if (nodeSteps == null)                    nodeSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Step");                List<XmlNode> oldNodeSteps = new List<XmlNode>();                foreach (XmlNode nodeTemp in nodeSteps)                {                    oldNodeSteps.Add(nodeTemp.Clone());                }                XmlNodeList backSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/BakeStep");                if (backSteps == null)                    backSteps = docTo.SelectNodes($"Aitex/TableRecipeData/BakeStep");                List<XmlNode> oldBackNodeSteps = new List<XmlNode>();                foreach (XmlNode nodeTemp in backSteps)                {                    oldBackNodeSteps.Add(nodeTemp.Clone());                }                ObservableCollection<StepDataItem> stepListTo = isSelectA ? StepListA : StepListB;                if (nodeModule == null)                {                    return;                }                foreach (StepDataItem item in stepListTo)                {                    bool isOverOf = true;                    foreach (XmlNode xmlNode in oldNodeSteps)                    {                        string stepNumber = xmlNode.Attributes["StepNo"].Value;                        if (item.StepNumber == stepNumber)                        {                            isOverOf = false;                            break;                        }                    }                    if (isOverOf)                    {                        XmlElement DeviceTree = docTo.CreateElement("Step");                        DeviceTree.SetAttribute("StepNo", (oldNodeSteps.Count + 1).ToString());                        DeviceTree.SetAttribute("Name", item.StepName);                        nodeModule.AppendChild(DeviceTree);                    }                }                nodeSteps = docTo.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/Step");                foreach (XmlNode nodeStep in nodeSteps)                {                    string stepNumber = nodeStep.Attributes["StepNo"].Value;                    ObservableCollection<ParamDataItem> paramList =                        isSelectA ? _mapStepParamA[stepNumber] : _mapStepParamB[stepNumber];                    foreach (var param in paramList)                    {                        (nodeStep as XmlElement).SetAttribute(param.ParamName, param.ParamValue);                    }                }                foreach (XmlNode nodeStep in backSteps)                {                    nodeModule.AppendChild(nodeStep);                }                string backText = getXmlText(isSelectA ? _domA : _domB);                LoadDataByRecipeContent(backText, isSelectA);                Recompare();                SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);                if (isSelectA)                {                    BackInnerXmlTextA.Add(backText);                }                else                {                    BackInnerXmlTextB.Add(backText);                }            }            catch (Exception ex)            {                LOG.Write(ex.Message);            }        }        private string getXmlText(XmlDocument xmlDocument)        {            (new RecipeProvider()).SaveRecipe("", "RecipeTemp", xmlDocument.InnerXml);            var _recipeProvider = new RecipeProvider();            var recipeContent = _recipeProvider.LoadRecipe("", "RecipeTemp", false);            return recipeContent;        }        public void ParamCopyToRight(ParamDataItem paramData)        {            string temp = "";            if (StepSelectionA != null)                temp = StepSelectionA.StepNumber;            ParamCopy(paramData, true);            if (!string.IsNullOrEmpty(temp))            {                foreach (StepDataItem tempStep in StepListA)                {                    if (tempStep.StepNumber == temp)                    {                        StepSelectionA = tempStep;                        break;                    }                }            }        }        public void ParamCopyToLeft(ParamDataItem paramData)        {            string temp = "";            if (StepSelectionB != null)                temp = StepSelectionB.StepNumber;            ParamCopy(paramData, false);            if (!string.IsNullOrEmpty(temp))            {                foreach (StepDataItem tempStep in StepListB)                {                    if (tempStep.StepNumber == temp)                    {                        StepSelectionB = tempStep;                        break;                    }                }            }        }        private void ParamCopy(ParamDataItem paramData, bool isFromA)        {            ParamDataItem paramFrom = paramData;            StepDataItem stepFrom = isFromA ? StepSelectionA : StepSelectionB;            Dictionary<string, ObservableCollection<ParamDataItem>> mapFrom = isFromA ? _mapStepParamA : _mapStepParamB;            Dictionary<string, ObservableCollection<ParamDataItem>> mapTo = isFromA ? _mapStepParamB : _mapStepParamA;            if (mapTo.ContainsKey(stepFrom.StepNumber))            {                foreach (var paramTo in mapTo[stepFrom.StepNumber])                {                    if (paramTo.ParamName != paramFrom.ParamName)                        continue;                    paramTo.ParamValue = paramFrom.ParamValue;                    paramTo.IsDiff = paramFrom.IsDiff = false;                    paramTo.IsExtra = paramFrom.IsExtra = false;                    paramFrom.InvokePropertyChanged();                    paramTo.InvokePropertyChanged();                    break;                }            }            bool isDiff = false;            foreach (var paramListFrom in mapFrom[stepFrom.StepNumber])            {                if (paramListFrom.IsDiff)                {                    isDiff = true;                    break;                }            }            stepFrom.IsDiff = isDiff;            stepFrom.InvokePropertyChanged();            ObservableCollection<StepDataItem> stepListTo = isFromA ? StepListB : StepListA;            foreach (var stepTo in stepListTo)            {                if (stepTo.StepNumber == stepFrom.StepNumber)                {                    isDiff = false;                    foreach (var paramListTo in mapTo[stepTo.StepNumber])                    {                        if (paramListTo.IsDiff)                        {                            isDiff = true;                            break;                        }                    }                    stepTo.IsDiff = isDiff;                    stepTo.InvokePropertyChanged();                    break;                }            }            CopyToInnerXml(!isFromA);        }        public void LineCopyToLeft(LineDataItem lineData)        {            LineCopy(lineData, false);        }        public void LineCopyToRight(LineDataItem lineData)        {            LineCopy(lineData, true);        }        public void LineCopy(LineDataItem lineData, bool isFromA)        {            try            {                LineDataItem lineFrom = lineData;                ObservableCollection<LineDataItem> lineListTo = isFromA ? WholeListB : WholeListA;                Dictionary<string, LineDataItem> mapFrom = isFromA ? _mapLineTextA : _mapLineTextB;                Dictionary<string, LineDataItem> mapTo = isFromA ? _mapLineTextB : _mapLineTextA;                foreach (var lineTo in lineListTo)                {                    if (lineTo.LineNumber != lineFrom.LineNumber)                        continue;                    lineTo.LineText = lineFrom.LineText;                    lineTo.IsDiff = lineFrom.IsDiff = false;                    lineTo.IsExtra = lineFrom.IsExtra = false;                    break;                }                string recipeContent = "";                if (isFromA)                {                    for (int i = 0; i < WholeListB.Count; i++)                    {                        recipeContent += WholeListB[i].LineText + ((i == WholeListB.Count - 1) ? "" : "\r\n");                    }                }                else                {                    for (int i = 0; i < WholeListA.Count; i++)                    {                        recipeContent += WholeListA[i].LineText + ((i == WholeListB.Count - 1) ? "" : "\r\n");                    }                }                CopyToInnerXml(recipeContent, !isFromA);                LoadDataByRecipeContent(recipeContent, !isFromA);                Recompare();                SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);            }            catch (Exception ex)            {                LOG.Write(ex.Message);            }        }        private void CopyToInnerXml(string recipeContent, bool isSelectA)        {            XmlDocument doc = isSelectA ? _domA : _domB;            doc.InnerXml = recipeContent;            if (isSelectA)            {                BackInnerXmlTextA.Add(recipeContent);            }            else            {                BackInnerXmlTextB.Add(recipeContent);            }        }        public void SaveA()        {            Save(true);        }        public void SaveB()        {            Save(false);        }        private void Save(bool isSelectA)        {            XmlDocument doc = isSelectA ? _domA : _domB;            XmlNodeList nodeSteps = doc.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{_module}']/Step");            if (nodeSteps == null)                nodeSteps = doc.SelectNodes($"Aitex/TableRecipeData/Step");            if (isSelectA)            {                (new RecipeProvider()).SaveRecipe("", RecipeA, doc.InnerXml);            }            else            {                (new RecipeProvider()).SaveRecipe("", RecipeB, doc.InnerXml);            }        }        public void UndoA()        {            string xmlData = "";            string temp = "";            if (StepSelectionB != null)                temp = StepSelectionB.StepNumber;            for (var i = BackInnerXmlTextA.Count - 1; i >= 0;)            {                if (i > 0)                {                    xmlData = BackInnerXmlTextA[i - 1];                    BackInnerXmlTextA.RemoveAt(i);                }                else                    xmlData = BackInnerXmlTextA[0];                break;            }            //_domA.InnerXml = xmlData;            LoadDataByRecipeContent(xmlData, true);            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);            if (!string.IsNullOrEmpty(temp))            {                foreach (StepDataItem tempStep in StepListB)                {                    if (tempStep.StepNumber == temp)                    {                        StepSelectionB = tempStep;                        break;                    }                }            }        }        public void UndoB()        {            string xmlData = "";            string temp = "";            if (StepSelectionA != null)                temp = StepSelectionA.StepNumber;            for (var i = (BackInnerXmlTextB.Count - 1); i >= 0;)            {                if (i > 0)                {                    xmlData = BackInnerXmlTextB[i - 1];                    BackInnerXmlTextB.RemoveAt(i);                }                else                    xmlData = BackInnerXmlTextB[0];                break;            }            //_domB.InnerXml = xmlData;            LoadDataByRecipeContent(xmlData, false);            Recompare();            SyncShowDiffSteps(IsShowDiffSteps, IsCompareBySName);            if (!string.IsNullOrEmpty(temp))            {                foreach (StepDataItem tempStep in StepListA)                {                    if (tempStep.StepNumber == temp)                    {                        StepSelectionA = tempStep;                        break;                    }                }            }        }        private bool _isStepModel = true;        public bool IsStepModel        {            get { return _isStepModel; }            set            {                _isStepModel = value;                _isWholeModel = !_isStepModel;                StepVisibility = _isStepModel ? Visibility.Visible : Visibility.Hidden;                WholeVisibility = _isWholeModel ? Visibility.Visible : Visibility.Hidden;                InvokePropertyChanged(nameof(IsStepModel));                InvokePropertyChanged(nameof(IsWholeModel));                InvokePropertyChanged(nameof(StepVisibility));                InvokePropertyChanged(nameof(WholeVisibility));            }        }        private bool _isWholeModel;        public bool IsWholeModel        {            get { return _isWholeModel; }            set            {                _isWholeModel = value;                _isStepModel = !_isWholeModel;                StepVisibility = _isStepModel ? Visibility.Visible : Visibility.Hidden;                WholeVisibility = _isWholeModel ? Visibility.Visible : Visibility.Hidden;                InvokePropertyChanged(nameof(IsWholeModel));                InvokePropertyChanged(nameof(IsStepModel));                InvokePropertyChanged(nameof(StepVisibility));                InvokePropertyChanged(nameof(WholeVisibility));            }        }        public Visibility StepVisibility        {            get; set;        }        public Visibility WholeVisibility        {            get; set;        }        private bool _isShowDiffSteps;        public bool IsShowDiffSteps        {            get { return _isShowDiffSteps; }            set            {                _isShowDiffSteps = value;                _isShowAllSteps = !_isShowDiffSteps;                SyncShowDiffSteps(_isShowDiffSteps, _isCompareBySName);                InvokePropertyChanged(nameof(IsShowDiffSteps));                InvokePropertyChanged(nameof(IsShowAllSteps));            }        }        private bool _isShowAllSteps = true;        public bool IsShowAllSteps        {            get { return _isShowAllSteps; }            set            {                _isShowAllSteps = value;                _isShowDiffSteps = !_isShowAllSteps;                SyncShowDiffSteps(_isShowDiffSteps, _isCompareBySName);                InvokePropertyChanged(nameof(IsShowAllSteps));                InvokePropertyChanged(nameof(IsShowDiffSteps));            }        }        private bool _isShowDiffParams;        public bool IsShowDiffParams        {            get { return _isShowDiffParams; }            set            {                _isShowDiffParams = value;                SyncShowDiffParams(_isShowDiffParams);                _isShowAllParams = !_isShowDiffParams;                InvokePropertyChanged(nameof(IsShowDiffParams));                InvokePropertyChanged(nameof(IsShowAllParams));            }        }        private bool _isShowAllParams = true;        public bool IsShowAllParams        {            get { return _isShowAllParams; }            set            {                _isShowAllParams = value;                _isShowDiffParams = !_isShowAllParams;                SyncShowDiffParams(_isShowDiffParams);                InvokePropertyChanged(nameof(IsShowDiffParams));                InvokePropertyChanged(nameof(IsShowAllParams));            }        }        private bool _isCompareByStep = true;        public bool IsCompareByStep        {            get { return _isCompareByStep; }            set            {                _isCompareByStep = value;                _isCompareBySName = !_isCompareByStep;                SyncShowDiffSteps(_isShowDiffSteps, _isCompareBySName);                InvokePropertyChanged(nameof(IsCompareByStep));                InvokePropertyChanged(nameof(IsCompareBySName));            }        }        private bool _isCompareBySName;        public bool IsCompareBySName        {            get { return _isCompareBySName; }            set            {                _isCompareBySName = value;                _isCompareByStep = !_isCompareBySName;                SyncShowDiffSteps(_isShowDiffSteps, _isCompareBySName);                InvokePropertyChanged(nameof(IsCompareByStep));                InvokePropertyChanged(nameof(IsCompareBySName));            }        }        private void SyncShowDiffSteps(bool isShowDiffSteps, bool isCompareBySName)        {            if (StepListA == null || StepListB == null)                return;            foreach (var item in StepListA)            {                item.IsHidden = (IsShowDiffSteps ? (item.IsDiff == false && item.IsExtra == false) : false) || (isCompareBySName ? (item.IsDiffName || item.IsExtra == true) : false);                item.InvokePropertyChanged();            }            foreach (var item in StepListB)            {                item.IsHidden = (IsShowDiffSteps ? (item.IsDiff == false && item.IsExtra == false) : false) || (isCompareBySName ? (item.IsDiffName || item.IsExtra == true) : false);                item.InvokePropertyChanged();            }            NotifyOfPropertyChange(nameof(StepListA));            NotifyOfPropertyChange(nameof(StepListB));        }        private void SyncShowDiffParams(bool isShowDiffParams)        {            if (ParamListA == null || ParamListB == null)                return;            if (isShowDiffParams)            {                foreach (var item in ParamListA)                {                    if (item.IsDiff == false && item.IsExtra == false)                    {                        item.IsHidden = isShowDiffParams;                        item.InvokePropertyChanged();                    }                }                foreach (var item in ParamListB)                {                    if (item.IsDiff == false && item.IsExtra == false)                    {                        item.IsHidden = isShowDiffParams;                        item.InvokePropertyChanged();                    }                }            }            else            {                foreach (var item in ParamListA)                {                    item.IsHidden = isShowDiffParams;                    item.InvokePropertyChanged();                }                foreach (var item in ParamListB)                {                    item.IsHidden = isShowDiffParams;                    item.InvokePropertyChanged();                }            }            NotifyOfPropertyChange(nameof(ParamListA));            NotifyOfPropertyChange(nameof(ParamListB));        }    }}
 |