wpf 中MVVM模式概要

一、MVVM的Model、View、ViewModel分工

1.View

  • 负责界面和显示,界面构成元素有window, controls, page, dataTemplete, custom
    controls….
  • 代码通常有XAML和XAML.CS组成,但后台代码应该很少
  • 通过DataContext和ViewModel绑定不直接和Model交互!
  • 控件可以和ViewModel的公共属性绑定,update需要双向绑定
  • 控件可以触发Behavior/Command调用ViewModel的方法,Command是View到ViewModel的单向通讯 (View中触发事件,ViewModel中处理事件)

2.ViewModel

  • 主要包括界面逻辑和模型数据封装,Behavior/Command事件响应,绑定的属性定义等
  • ViewModel继承Model类,或者是Model的继承类
    是view和model的桥梁,是对Model的抽象,例如,model中数据格式是“年月日”,可以在viewModel中转换model中的数据为“日月年”以供视图(view)显示。
  • 维护视图状态
  • 实现属性或集合的change notification
    -在这里插入图片描述

3. Model

  • 数据和业务逻辑
  • 客户端领域模型
  • 由data entities, business objects, repositories and services构成
  • 可以实现属性或集合的change notification
  • 可以实现validation 接口例如 IDataErrorInfo
    在这里插入图片描述

二、 MVVM

View和ViewModel数据绑定和交互

View和ViewModel主要通过数据绑定和Command/Behavior进行交互,如下图所示:

在这里插入图片描述

 private void InitializeCommandHandlers()
        {
            //突发事件
            AccidentsWindowHelper.InitializeParentCommandHandlers(this);
            //事件线索
            this.AccidentCluesCommandHandler();
            //预案管理
            this.PlansCommandHandler();
            //复制Plot到当前打开的文档
            this.CommandBindings.Add(new CommandBinding(Commands.HomeCopyPlotToCurrentWord, CopyPlotToWordHandler, (sender, e) => {
                e.CanExecute = e.Parameter is MapPlot &&
                LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;// MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED;
            }));

            //态势标绘
            MapPlotHelper.InitializeParentCommandHandlers(this);

            //综合态势
            MapPlotStateHelper.InitializeParentCommandHandlers(this);

            //大数据资源池
            this.BigDataResPoolCommandHandler();

            //显示首页列表
            this.CommandBindings.Add(new CommandBinding(Commands.HomePage, HomePageCommandHandler, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;// MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED;
            }));

            //创建WORD文档
            this.CommandBindings.Add(new CommandBinding(Commands.CreateWord, CreateWordCommandHandler, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ && MainWindowViewModel.Current.IsWordAvailable;
#else
                    e.CanExecute = false;
#endif
            }));
            //选择已经显示的文档
            this.CommandBindings.Add(new CommandBinding(Commands.SelectOpeningIntel, (sender, arg) => {
                IntelBase intel = arg.Parameter as IntelBase;
                try {
                    this.WordContainer.WordControl.ShowDocument(intel.ID);
                    OpeningIntelsViewModel.Current.ShowIntel(intel.ID);
                } catch (Exception ex) {
                    LogHelper.e("MainWindow.WordNavigator.OnItemSelectedEvent -> ", ex);
                }
            }, (sender, e) => {
                e.CanExecute = e.Parameter != null;
            }));
            //关闭显示的文档 
            this.CommandBindings.Add(new CommandBinding(Commands.CloseOpeningIntel, CloseOpeningIntelCommandHandler));

            //修改产品标题
            this.CommandBindings.Add(new CommandBinding(Commands.EditProductTitle, EditProductTitleCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        // && (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN) 
                        && product.IsDraft;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //上报产品 
            this.CommandBindings.Add(new CommandBinding(Commands.ReportProduct, ReportProductCommandHandler, (sender, e) => {
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && !UnitHelper.IsTopUnit(UnitHelper.MyUnit);
                }
                else if (e.Parameter is Information information)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && !UnitHelper.IsTopUnit(UnitHelper.MyUnit);
                }
                else if (e.Parameter is PaperWork paperwork)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                       && paperwork.File != null && (paperwork.File.FileType == IntelFileType.XMLDOC ||
                    paperwork.File.FileType == IntelFileType.WORD) && !UnitHelper.IsTopUnit(UnitHelper.MyUnit);
                }
                else
                {
                    e.CanExecute = false;
                }
            }));
            //上报突发事件 
            this.CommandBindings.Add(new CommandBinding(Commands.ReportAccident, ReportAccidentCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && !UnitHelper.IsTopUnit(UnitHelper.MyUnit);
                }
                else if (e.Parameter is Information information)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && !UnitHelper.IsTopUnit(UnitHelper.MyUnit);
                }
                else if (e.Parameter is PaperWork paperwork)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                       && paperwork.File != null && (paperwork.File.FileType == IntelFileType.XMLDOC ||
                    paperwork.File.FileType == IntelFileType.WORD) && !UnitHelper.IsTopUnit(UnitHelper.MyUnit);
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));


            //查看推送信息
            this.CommandBindings.Add(new CommandBinding(Commands.ViewPushInfo, ViewPushInfoCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = product.IsPushed && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //另存为新产品
            this.CommandBindings.Add(new CommandBinding(Commands.SaveAsNewProduct, SaveAsNewProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }
                else e.CanExecute = false;
#else
                    e.CanExecute = false;
#endif
            }));

            //发送产品到其他单位
            this.CommandBindings.Add(new CommandBinding(Commands.SendProduct, SendProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }

                else if (e.Parameter is Information information)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }
                else if (e.Parameter is PaperWork paperwork)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }

                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //产品推送
            this.CommandBindings.Add(new CommandBinding(Commands.PushProduct, PushProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = (!product.IsPushed) && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //取消产品推送
            this.CommandBindings.Add(new CommandBinding(Commands.CancelPushProduct, CancelPushProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = product.IsPushed && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //归档
            this.CommandBindings.Add(new CommandBinding(Commands.ArchiveProduct, ArchiveProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && product.IsDraft;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //重新编辑
            this.CommandBindings.Add(new CommandBinding(Commands.ReeditProduct, ReeditProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && !product.IsDraft;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));

            //添加本地文件为产品
            this.CommandBindings.Add(new CommandBinding(Commands.ImportLocalWordAsProduct,
                ImportLocalWordAsProductCommandHandler, (sender, e) => {
#if !READER
                    e.CanExecute = true;
#else
                    e.CanExecute = false;
#endif
                }));

            //评价接收到的素材
            this.CommandBindings.Add(new CommandBinding(Commands.CommentInformation, CommentInformationCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Information i)
                {
                    e.CanExecute = (LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ && i.Receiver != null && UnitHelper.IsMyUnit(i.Receiver.ReceiveUnit));
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //查看上报素材的评价结果
            this.CommandBindings.Add(new CommandBinding(Commands.ViewCommentInformation, ViewCommentInformationCommandHandler, (sender, e) => {
                if (e.Parameter is Information i)
                {
                    e.CanExecute = (LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ &&
                    UnitHelper.IsMyUnit(i.SendUnit) && i.HasEvaluated);
                }
                else
                {
                    e.CanExecute = false;
                }
            }));
            //标记优秀成果
            this.CommandBindings.Add(new CommandBinding(Commands.MarkFavorite, MarkFavoriteCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Information i)
                {
                    e.CanExecute = (LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ &&
                    i.Receiver != null && UnitHelper.IsMyUnit(i.Receiver.ReceiveUnit) && !i.IsExcellent);//是本单位接收的素材且未标注
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //标记优秀成果
            this.CommandBindings.Add(new CommandBinding(Commands.MarkOrCancelFavorite, MarkOrCancelFavoriteCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Information i)
                {
                    e.CanExecute = (LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ &&
                    i.Receiver != null && UnitHelper.IsMyUnit(i.Receiver.ReceiveUnit));//是本单位接收的素材
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //取消标记优秀成果
            this.CommandBindings.Add(new CommandBinding(Commands.CancelFavorite, CancelFavoriteCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Information i)
                {
                    e.CanExecute = (LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ &&
                    i.Receiver != null && UnitHelper.IsMyUnit(i.Receiver.ReceiveUnit) && i.IsExcellent);//是本单位接收的素材且已标注
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));

            //为产品添加密码,将产品转换为带密码产品
            this.CommandBindings.Add(new CommandBinding(Commands.ProductCreatePassword, (sender, arg) => {
                Product p = arg.Parameter as Product;
                if (p == null || p.Type != IntelType.PRODUCT)
                    return;
                tryCloseOpenIntel(p);

                ProductSecretCreateWindow win = new ProductSecretCreateWindow();
                win.Product = p;
                win.ShowDialog();
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));


            //修改带密码产品的密码
            this.CommandBindings.Add(new CommandBinding(Commands.ProductUpdatePassword, (sender, arg) => {
                Product p = arg.Parameter as Product;
                if (p == null || !p.IsSecret)
                    return;
                ProductSecretUpdateWindow win = new ProductSecretUpdateWindow();
                win.Product = p;
                win.ShowDialog();
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));

            //删除带密码产品的密码
            this.CommandBindings.Add(new CommandBinding(Commands.ProductDeletePassword, (sender, arg) => {
                Product p = arg.Parameter as Product;
                if (p == null || !p.IsSecret)
                    return;

                tryCloseOpenIntel(p);

                ProductSecretDeleteWindow win = new ProductSecretDeleteWindow();
                win.Product = p;
                win.ShowDialog();
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));
            //带密码产品验证授权
            this.CommandBindings.Add(new CommandBinding(Commands.ProductVerifyPassword, (sender, arg) => {
                Product p = arg.Parameter as Product;
                if (p == null || !p.IsSecret)
                    return;
                ProductSecretVerifyWindow win = new ProductSecretVerifyWindow();
                win.Product = p;
                win.ShowDialog();
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            //打开一个产品
            this.CommandBindings.Add(new CommandBinding(Commands.OpenProduct, OpenProductCommandHandler, (sender, e) => {
                e.CanExecute = e.Parameter is Product
                    && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //打开一个素材
            this.CommandBindings.Add(new CommandBinding(Commands.OpenInformation, OpenInformationCommandHandler, (sender, e) => {
                e.CanExecute = e.Parameter is Information
                    && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //打印WORD文档
            this.CommandBindings.Add(new CommandBinding(Commands.PrintWord, (sender, args) => {
                PrintSettingWindow dialog = new PrintSettingWindow();
                dialog.Control = this.WordContainer.WordControl;
                //dialog.ShowDialog();
                dialog.Owner = this;
                dialog.Closed += Dialog_Closed;
                ShowWindow(dialog);

                //this.WordContainer.WordControl.Print();
            }, (sender, e) => {
                e.CanExecute = e.Parameter != null;
            }));

            //保存产品
            this.CommandBindings.Add(new CommandBinding(Commands.SaveProduct, (sender, arg) => {
                IntelBase p = null;
                if (arg.Parameter is Product product)
                {
                    p = product;
                }
                else if (arg.Parameter is ReportIntelProduct reportIntelProdu)
                {
                    p = reportIntelProdu;
                }

                if (p == null)
                    return;

                if (IsTrue(ConfigViewModel.Current.IsRecomEnable))
                {
                    ServiceHelper.RecomLevel(p.ID, (errno1, message1, level) => {
                        if (errno1 == ErrorNo.SUCCESS)
                        {
                            ServiceHelper.RecomSecurity(p.ID, (errno2, message2, security) => {
                                if (errno2 == ErrorNo.SUCCESS)
                                {
                                    Dispatcher.BeginInvoke((Action)(() => {
                                        WordContainer.InnerWindow.Reload(p, level, security);
                                        WordContainer.InnerWindow.Show();
                                    }));
                                }
                            });
                        }
                    });
                }

                if (IsTrue(ConfigViewModel.Current.IsAreaCorrectEnable))
                {
                    string content = this.WordContainer.WordControl.GetText();
                    if (content != null && content.Length > 0)
                    {
                        ServiceHelper.DistrictCheck(content, (errno, message, error_districts) => {
                            if (errno == ErrorNo.SUCCESS &&
                            error_districts != null && error_districts.Length > 0)
                            {
                                string[] tokens = error_districts.Split(
                                    new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                                if (tokens != null && tokens.Length > 0)
                                {
                                    List<string> tokenList = new List<string>();
                                    foreach (var token in tokens)
                                        if (!tokenList.Contains(token))
                                            tokenList.Add(token);

                                    Dispatcher.BeginInvoke((Action)(() => {
                                        this.WordContainer.WordControl.HitHighlight(tokenList.ToArray());
                                    }));
                                }
                            }
                        });
                    }
                }

                if (IsTrue(ConfigViewModel.Current.IsRecomEnable))
                    TryRecomDoc(p);

                this.Waiting("正在保存产品...", true, true);
                try
                {
                    if (!this.WordContainer.WordControl.Save(p.ID, true))
                    {
                        //this.CancelWaiting("保存失败!", true);
                        this.CancelWaiting();
                        this.ForceCancelWaiting();
                        ShowWarning("保存失败!");
                    }
                }
                catch (Exception ex)
                {
                    //this.CancelWaiting("保存失败:" + ex.Message, true);
                    this.CancelWaiting();
                    this.ForceCancelWaiting();
                    ShowWarning("保存失败:" + ex.Message);
                    Log.LogHelper.e(ex.StackTrace);
                    Exception inner = ex.InnerException;
                    while (inner != null)
                    {
                        Log.LogHelper.e(inner.StackTrace);
                        inner = inner.InnerException;
                    }
                }
            }, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && product.IsDraft;
                }
                else if (e.Parameter is ReportIntelProduct reportIntelProduct)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && reportIntelProduct.IsDraft;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));

            //将本地文件作为素材报告给上级
            this.CommandBindings.Add(new CommandBinding(Commands.SendLocalFilesAsInformation, (sender, arg) => {
                SendFileViewModel.Current.IsInformation = true;
                this.ShowDialog(new SendFilesWindow());
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                    e.CanExecute = false;
#endif
            }));

            //将本地文件作为公文发送给其他单位
            this.CommandBindings.Add(new CommandBinding(Commands.SendLocalFilesAsPaperWork, (sender, arg) => {
                SendFileViewModel.Current.IsInformation = false;
                this.ShowDialog(new SendFilesWindow());
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                    e.CanExecute = false;
#endif
            }));

            //删除产品
            this.CommandBindings.Add(new CommandBinding(Commands.DeleteProduct, DeleteProductCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && product.IsDraft;
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //解除锁定产品
            this.CommandBindings.Add(new CommandBinding(Commands.UnlockProduct, (sender, arg) => {
                Product p = arg.Parameter as Product;
                if (p == null || !p.IsLocked || !p.IsDraft)
                    return;
                //尝试结束自己和别人的锁定
                ProductIds.RemoveLockedProductId(p.ID);
                this.Waiting("解除锁定...", true, true);
                try
                {
                    CommuService.Instance.UnlockProduct(p.ID, (status, msg, msgBean) => {
                        if (status != LongLink.Bean.EnumStatus.Success)
                        {
                            //this.CancelWaiting("解除锁定失败:" + result1, true);
                            this.CancelWaiting();
                            this.ForceCancelWaiting();
                            ShowWarning("解除锁定失败:" + msg);
                        }
                        else
                        {
                            p.IsLocked = false;
                            p.LockerId = "";
                            p.Save();

                            this.WordContainer.WordControl.UnlockDocument(p.ID);
                            //this.ShowMessage(ErrorNo.SUCCESS, "解除锁定成功!");
                            this.CancelWaiting("解除锁定成功。", true);
                            this.ForceCancelWaiting();
                        }
                    });
                }
                catch (Exception ex)
                {
                    Log.LogHelper.w(ex.StackTrace);
                    //this.CancelWaiting("解除锁定失败:" + result1, true);
                    this.CancelWaiting();
                    this.ForceCancelWaiting();
                    ShowWarning("解除锁定失败:" + ex.Message);
                }

            }, (sender, e) => {
#if !READER
                if (e.Parameter is Product product)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && (product.IsLocked /*&& product.LockerId == MainWindowViewModel.Current.Me.SN*/)
                        && product.IsDraft;
                }
                else
                    e.CanExecute = false;
#else
                    e.CanExecute = false;
#endif
            }));

            //修改分类
            this.CommandBindings.Add(new CommandBinding(Commands.ChangeClass, (sender, arg) => {
                this.ShowDialog(new ChangeClassWindow(arg.Parameter as Product));
            }, (sender, e) => {
#if !READER
                e.CanExecute = e.Parameter is Product
                    && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));
            //修改密级
            this.CommandBindings.Add(new CommandBinding(Commands.ChangeSecurity, (sender, arg) => {
                this.ShowDialog(new ChangeSecurityWindow(arg.Parameter as IntelBase));
            }, (sender, e) => {
#if !READER
                e.CanExecute = e.Parameter is IntelBase
                    && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));
            //修改优先级
            this.CommandBindings.Add(new CommandBinding(Commands.ChangeLevel, (sender, arg) => {
                this.ShowDialog(new ChangeLevelWindow(arg.Parameter as IntelBase));
            }, (sender, e) => {
#if !READER
                e.CanExecute = e.Parameter is IntelBase
                    && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));
            //下载到本地并打开
            this.CommandBindings.Add(new CommandBinding(Commands.GetIntelAndOpen, GetIntelAndOpenCommandHandler, (sender, e) => {
                e.CanExecute = e.Parameter is IntelBase
                    && LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //显示弹出消息
            this.CommandBindings.Add(new CommandBinding(Commands.ShowPopupMessage, (sender, args) => {
                if (args.Parameter is StatusBarViewModel.PopupMessageArgument arg) {
                    this.StatusBar.ShowPopMessage(arg.Content, arg.ActionContent, arg.ActionHandler, arg.ActionParam);
                }
            }));

            //新建通知
            this.CommandBindings.Add(new CommandBinding(Commands.NewNotice, (sender, args) => {
#if !READER
                NoticesViewModel.Current.ReplyingIntel = null;
                this.ShowDialog(new PostQuickWindow()
                {
                    OnManageReplyOptions = OnManageReplyOptions,
                });
#else
#endif
            }));
            //回复通知
            this.CommandBindings.Add(new CommandBinding(Commands.ReplyNotice, (sender, args) => {
#if !READER
                NoticesViewModel.Current.PostingNotice.Content = args.Parameter as string;
                this.ShowDialog(new PostQuickWindow()
                {
                    OnManageReplyOptions = OnManageReplyOptions,
                });
#else
#endif
            }));
            //管理回复选项
            this.CommandBindings.Add(new CommandBinding(Commands.ManageReplyOptions, (sender, arg) => {
#if !READER
                this.OnManageReplyOptions();
#else
#endif
            }));

#if !READER
            //导入资料文件
            this.CommandBindings.Add(new CommandBinding(Commands.ImportFilesToCategory, (sender, arg) => {
                this.ShowDialog(new ImportFilesToCategoryWindow());
            }));
            //移动分类
            this.CommandBindings.Add(new CommandBinding(Commands.MoveCategoryToCategory, MoveCategoryOrDocumentToCategoryCommandHandler));
            //打开资料文件
            this.CommandBindings.Add(new CommandBinding(Commands.OpenDocument, OpenDocumentCommandHandler));
            //移动资料文件
            this.CommandBindings.Add(new CommandBinding(Commands.MoveDocumentToCategory, MoveCategoryOrDocumentToCategoryCommandHandler));
            //向资料中导入本地文件夹
            this.CommandBindings.Add(new CommandBinding(Commands.ImportFolderToCategory, (sender, arg) => {
                this.ShowDialog(new ImportFolderToCategoryWindow());
            }));
            //删除资料文件
            this.CommandBindings.Add(new CommandBinding(Commands.DeleteDocument, DeleteDocumentCommandHandler));
            //删除分类(仅分类)
            this.CommandBindings.Add(new CommandBinding(Commands.DeleteCategory, DeleteCategoryCommandHandler));
            //删除分类及下属文件
            this.CommandBindings.Add(new CommandBinding(Commands.DeleteCategoryAndAll, DeleteCategoryAndAllCommandHandler));
#else
#endif

            //打开发文
            this.CommandBindings.Add(new CommandBinding(Commands.OpenSent, OpenSentCommandHandler));

            //打开公文
            this.CommandBindings.Add(new CommandBinding(Commands.OpenPaperWork, OpenPaperWorkCommandHandler));

            //撤回公文
            this.CommandBindings.Add(new CommandBinding(Commands.DeletePaperWork, DeletePaperWorkCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is PaperWork paperwork)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && paperwork.SendUnit != null && UnitHelper.IsMyUnit(paperwork.SendUnit.Code);
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //撤回素材
            this.CommandBindings.Add(new CommandBinding(Commands.DeleteInformation, DeleteInformationCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Information information)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && information.SendUnit != null && UnitHelper.IsMyUnit(information.SendUnit.Code);
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //撤回通知
            this.CommandBindings.Add(new CommandBinding(Commands.DeleteNotice, DeleteNoticeCommandHandler, (sender, e) => {
#if !READER
                if (e.Parameter is Notice notice)
                {
                    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        //&& (!product.IsLocked || product.LockerId == MainWindowViewModel.Current.Me.SN)
                        && notice.SendUnit != null && UnitHelper.IsMyUnit(notice.SendUnit.Code);
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                    e.CanExecute = false;
#endif
            }));
            //回复素材
            this.CommandBindings.Add(new CommandBinding(Commands.ReplyInformation, (sender, arg) => {
                NoticesViewModel.Current.ReplyingIntel = arg.Parameter as Information;
                this.ShowDialog(new PostQuickWindow() {
                    OnManageReplyOptions = OnManageReplyOptions,
                });
            }, (sender, e) => {
#if !READER
                if (e.Parameter is Information i && !(e.Parameter is Product))
                {
                    e.CanExecute = (LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/
                        && i.Receiver != null && UnitHelper.IsMyUnit(i.Receiver.ReceiveUnit));
                }
                else
                {
                    e.CanExecute = false;
                }
#else
                e.CanExecute = false;
#endif
            }));
            this.CommandBindings.Add(new CommandBinding(Commands.RefreshImmediately, (sender, arg) => {
                try
                {
                    if (WindowMenu != null && WindowMenu.DataContext == null)
                    {
                        WindowMenu.DataContext = this.DataContext;
                    }
                    LogHelper.i("Update CommandManager in RefreshImmediately Command");
                    CommandManager.InvalidateRequerySuggested();
                }
                catch
                {

                }
                new System.Threading.Tasks.Task(() => {
                    MainWindowViewModel.Current.RefrshSystemConfig();
                }).Start();
                MainWindowViewModel.Current.RefreshAll();
                StatusBarViewModel.Current.DynamicMessage = "";
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            this.CommandBindings.Add(new CommandBinding(Commands.ResetDataVersion, (sender, arg) => {
                //ver -= 1000;
                //if (ver < 0) ver = 0;
                //str = ver.ToString();
                Models.Database.Database.Instance.ClearVersions();

                MainWindowViewModel.Current.RefreshAll();
                StatusBarViewModel.Current.DynamicMessage = "";
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            this.CommandBindings.Add(new CommandBinding(Commands.ResetDataBase, (sender, arg) => {
                MessageBoxResult mbr = AyMessageBox.ShowQuestion("确定要重置数据库?", "重置数据库");
                if (mbr != MessageBoxResult.Yes) { return; }

                Models.Database.Database.Instance.Reset();
                MainWindowViewModel.Current.Intels.Reset();
                MainWindowViewModel.Current.RefreshAll();
                StatusBarViewModel.Current.DynamicMessage = "";
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            this.CommandBindings.Add(new CommandBinding(Commands.RecreateDataBase, (sender, arg) => {
                MessageBoxResult mbr = AyMessageBox.ShowQuestion("确定要重建数据库?", "重建数据库");
                if (mbr != MessageBoxResult.Yes) { return; }
                if (DBUtility.SQLite.SQLiteHelper.RecreateDb())
                {
                    Models.Database.Database.Instance.Reset();
                    MainWindowViewModel.Current.Intels.Reset();
                    MainWindowViewModel.Current.RefreshAll();
                    StatusBarViewModel.Current.DynamicMessage = "";
                    ShowInformation("重建数据库成功!");
                }
                else ShowWarning("重建数据库失败!");
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            this.CommandBindings.Add(new CommandBinding(Commands.HistoryProduct, (sender, arg) => {
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //显示文件列表
            this.CommandBindings.Add(new CommandBinding(Commands.ShowIntelsList, (sender, arg) => {
                if (this.IntelsDrawer.Visibility == Visibility.Collapsed) {
                    this.IntelsDrawer.Visibility = Visibility.Visible;
                } else {
                    this.IntelsDrawer.Visibility = Visibility.Collapsed;
                }
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            //显示待办事项窗口
            this.CommandBindings.Add(new CommandBinding(Commands.ShowTodoes, (sender, arg) => {
                this.ShowDialog(new TodoesWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            //显示突发事件窗口
            this.CommandBindings.Add(new CommandBinding(Commands.ShowIncidents, (sender, arg) => {
                this.ShowDialog(new IncidentsWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            //显示提醒窗口
            this.CommandBindings.Add(new CommandBinding(Commands.ShowReminders, (sender, arg) => {
                this.ShowDialog(new RemindersWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //显示优秀成果窗口
            this.ShoExcellentsCommandHandler();

            //显示即时消息
            this.CommandBindings.Add(new CommandBinding(Commands.ShowFields, ShowFieldsCommandHandler, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //全文检索
            this.CommandBindings.Add(new CommandBinding(Commands.FulltextSearch, FulltextSearchCommandHandler, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ && SearchViewModel.Current.CanFulltextSearch;
            }));
            //基于字段的检索
            this.CommandBindings.Add(new CommandBinding(Commands.FieldsSearch, FieldsSearchCommandHandler, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/ && SearchViewModel.Current.CanFieldsSearch;
            }));

            //系统配置
            this.CommandBindings.Add(new CommandBinding(Commands.SystemConfig, (sender, arg) => {
                Timers.Suspend(Timers.TimerID.TimerRefreshTemplates);
                ConfigViewModel.Current.WatchClassPropertyChanged(true);

                ConfigWindow cfgWin = new ConfigWindow();
                this.ShowDialog(cfgWin);

                ConfigViewModel.Current.WatchClassPropertyChanged(false);
                Timers.Resume(Timers.TimerID.TimerRefreshTemplates);
                IntelsDrawer.FilterTabConfigChanged();
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));
            //评价模板管理
            this.CommandBindings.Add(new CommandBinding(Commands.EvalTempConfig, (sender, arg) => {
                Timers.Suspend(Timers.TimerID.TimerEvaluationIndices);

                EvaluateTemplateWindow win = new EvaluateTemplateWindow();
                this.ShowDialog(win);

                Timers.Resume(Timers.TimerID.TimerEvaluationIndices);
            }, (sender, e) => {
#if !READER
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
#else
                e.CanExecute = false;
#endif
            }));

            //值班查看
            this.CommandBindings.Add(new CommandBinding(Commands.DutyConfig, (sender, arg) => {
                this.ShowDialog(new ViewDutyWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //打印查看
            this.CommandBindings.Add(new CommandBinding(Commands.PrintSearch, (sender, arg) => {
                this.ShowDialog(new ViewPrintWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //查看日志
            this.CommandBindings.Add(new CommandBinding(Commands.UserLogSearch, (sender, arg) => {
                this.ShowDialog(new ViewLogsWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //热点推荐
            this.RecommendSearchCommandHandler();

            //特有推荐
            this.InterestRecommendSearchCommandHandler();

            //评价统计
            this.CommandBindings.Add(new CommandBinding(Commands.EvaluateStat, (sender, arg) => {
                this.ShowDialog(new ViewEvaluateStatWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));

            //全屏编辑
            this.CommandBindings.Add(new CommandBinding(Commands.FullScreenEdit, (sender, arg) => {
                FullScreenEdit(true);
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined /*MainWindowViewModel.Current.Me.NetworkStatus == NetworkStatus.CONNECTED*/;
            }));
            //退出全屏编辑
            this.CommandBindings.Add(new CommandBinding(Commands.ExitFullScreenEdit, (sender, arg) => {
                FullScreenEdit(false);
            }));

            //显示统计详细信息
            this.StatDetailsCommandHandler();

            //显示统计分析信息
            this.StatAnalysisCommandHandler();

            //产品批量处理
            this.CommandBindings.Add(new CommandBinding(Commands.ProductBatchCommand, (sender, arg) => {
                ProductBatchWindow dialog = new ProductBatchWindow();//
                dialog.Owner = this;
                dialog.Closed += ProductBatchDialog_Closed;
                dialog.Closed += Dialog_Closed;
                ShowWindow(dialog);

                Inteligences products = MainWindowViewModel.Current.Intels.Products;
                foreach (IntelBase intel in products)
                {
                    if (((Product)intel).IsDraft)
                        ((Product)intel).IsDraftCheckVisible = true;
                }
            }, (sender, e) => {
#if !READER
                e.CanExecute = MainWindowViewModel.Current.Intels.ProductDraftCount > 0;
#else
                e.CanExecute = false;
#endif
            }));

            //素材标记采用
            this.CommandBindings.Add(new CommandBinding(Commands.MarkAdoptCommand, (sender, arg) => {
                IntelBase intel = null;
                if (arg.Parameter is Information)
                {
                    intel = arg.Parameter as Information;
                }
                if(arg.Parameter is PaperWork)
                {
                    intel = arg.Parameter as PaperWork;
                }
                this.ShowDialog(new MarkAdoptWindow(intel));

            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;
            }));
            //素材批量采用
            this.CommandBindings.Add(new CommandBinding(Commands.BatchAdoptCommand, (sender, arg) => {
                this.ShowWindow(new BatchAdoptWindow());
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;
            }));

            //取消标记采用
            //this.CommandBindings.Add(new CommandBinding(Commands.CancelMarkAdoptCommand, (sender, arg) => {
            //    Information information = arg.Parameter as Information;

            //    if (information == null) return;

            //    this.Waiting("正在取消采用标记...", true, true);

            //    ServiceApi.DeleteIntelAdoptDetail(information, (errno, message) => {
            //        if(errno != Zonkin.IPP.V1.Base.ErrorNo.ErrSuccess)
            //        {
            //            this.CancelWaiting();
            //            this.ForceCancelWaiting();
            //            ShowWarning("取消采用标记失败:" + message);
            //        }
            //        else
            //        {
            //            this.CancelWaiting("取消采用标记成功!", true);
            //            this.ForceCancelWaiting();
            //        }
            //    });
            //}, (sender, e) => {
            //    e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;
            //}));

            //报表上报
            this.CommandBindings.Add(new CommandBinding(Commands.ReportIntelCammend, (sender, arg) => {
                if (!ReportIntelWindowViewModel.Current.IsShowing)
                {
                    Point point = this.IndicatorControls.TranslatePoint(new Point(-400, IndicatorControls.ActualHeight), this);
                    ReportIntelWindow reportIntelWindow = new ReportIntelWindow()
                    {
                        Left = point.X,
                        Top = point.Y,
                        createReportIntelProductHandler = CreateReportIntelProductCommandHandler,
                        openReportIntelHandler = OpenReportIntelHandler,
                        mergeReportIntelHandler = MergeReportIntelInformationCommandHandler,
                        unlockReportIntelProductHandler = UnlockReportIntelHandler,
                        deleteReportIntelProduct = DeleteReportIntelProductCommandHandler,
                        convertNewReportProductHandler = ConvertNewReportProductCommandHandler
                    };
                    reportIntelWindow.Owner = this;
                    //this.ShowWindow(reportIntelWindow);
                    reportIntelWindow.Show();
                }
            }, (sender, e) => {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;
            }));
            //态势展示
            IncidentMapWindowHelper.InitializeParentCommandHandlers(this);
            //在线状态
            this.CommandBindings.Add(new CommandBinding(Commands.LoginStatus, (sender, arg) =>
            {
                LoginStatusWindow win = new LoginStatusWindow();
                this.ShowWindow(win);
                //BrowserHelper.OpenBrowserUrl(Webpages.GetUrl(Webpages.LOGIN_STATUS) + "?sn=" + Config.SN);
            }, (sender, e) =>
            {
                e.CanExecute = LongLink.LongLinkViewModel.Current.AppState == LongLink.AppState.Logined;
            }));
            //实施升级
            this.CommandBindings.Add(new CommandBinding(Commands.UpdateCommand, DoUpdate));
        }

有关Model(模型)和DTO的问题

在这里插入图片描述
前面说的Model是客户端的,但实际上Domail Model存在服务器端(靠近数据库)和那就需要和客户端搞映射DTO(Data Transfer Ojbect,数据传输对象,带序列化标记,用来远程调用)。在Silverlight中有个很方便的东西来实现这个DTO过程和序列化,那就是WCF RIA Service和DomainService。如果你创建一个简单的Silverlight应用并且调用WCF RIA Service,基本上会生成DTO Model: ObjectContext(EntityObject)。
在这里插入图片描述

MVVM的实践要点

1. View分离要彻底,不要有坏味道

视图(view)部分,xaml.cs 应该只有很少的代码或没有代码,如果你的xaml.cs包含大量的代码,那么很可能你MVVM用的不对头,需要检查其中代码的坏味道。Xaml和xaml.cs 只能包含处理界面、视图、显示样式、视图元素之间的交互、视图元素动画,等等的内容。

2. ViewModel要可测试

从重构的观点看,如果你的代码中ViewModel是可测试的,有详细的单元测试Unit Test,你的代码是OK的,否则需要检查其中的坏味道。

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是刘彦宏吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值