zoukankan      html  css  js  c++  java
  • 自定义工作流设计器

    第一部分
    基础工作,建立代码结构框架
    1.创建项目WorkflowDesignerControl
    1.1:WorkflowView和DesignSurface,workflowView是微软提供的工作流设计API,所有的操作都要在上面进行;DesignSurface是WorkflowView的设计时支持
    WorkflowView需要从中获得一些资源。
    1.2:工具箱和属性窗口也要放到WorkflowDesignerControl中
     

    Toolbox toolbox = new Toolbox(this);
      
    this.propertyGridSplitter.Panel1.Controls.Add(toolbox);
      toolbox.Dock 
    = DockStyle.Fill;
      toolbox.BackColor 
    = BackColor;
      toolbox.Font 
    = WorkflowTheme.CurrentTheme.AmbientTheme.Font; 

    2、在WorkflowDesignerControl加入ActivityLibrary的引用
      DesignerHostingApplication中加入ActivityLibrary和WorkflowDesignerControl的引用
      DesignerHostingApplication中加入System.Design,System.Drawing.Design,System.Workflow.Activities,System.Workflow.ComponentModel的引用

    3.所有自定义的Activitie放入一个project,这样基本的代码架构就建立好了。

    第二部分
    winfrom中集成可编程的wf设计器
    1.首先创建DesignerHostingApplication的解决方案
    重命名from1.cs为DesignerShell.cs,并加入工具条
    Toolstrip
     Name: toolStrip
     GripStyle: Hidden
     RenderMode: System
     Ensure the Dock property is set to Top
    将WorkflowDesignControl加入toolStrip
     Name: workflowDesignerControl
     Dock: Fill
    2.使设计器支持zooming
     

    public void ProcessZoom(int zoomFactor)
            
    {
                
    this.workflowView.Zoom = zoomFactor;
                
    this.workflowView.Update();
            }

    2.1:使用预定义的zoom levels 25%, 100% and 200%,zoom设计器in or out
     在DesignerShell.cs中调用ProcessZoom
     

    private void zoomDropDownMenuItem_Click(object sender, EventArgs e)
            
    {
                
    if (sender is ToolStripMenuItem)
                
    {
                    ToolStripMenuItem menuItem 
    = (ToolStripMenuItem)sender;

                    
    int zoomFactor = 0;

                    
    bool result = Int32.TryParse(menuItem.Tag.ToString(), out zoomFactor);

                    
    if (result)
                    
    {
                        
    this.workflowDesignerControl.ProcessZoom(zoomFactor);
                    }

                }

            }


    2.2:在toolstrip中加入dropdownButton并定义属性:
      Name: zoomDropDown
      DisplayStyle: Text
      Text: Zoom
      编辑DropDownButton,加入三个Item对应Text分别为:25% ,100%,200%
      每个item分别定义name和tag,分别为;mni25PercentZoom,25;mni100PercentZoom,100;mni200PercentZoom,200;
      并定义click事件
     
    3如何在wf中添加Activities(能在workflow中添加或删除Activitie,并能修改activity的属性)
    1.在WorkflowDesignerControl.cs中添加自定义的工具箱
     

    public WorkflowDesignerControl()
            
    {
                InitializeComponent();

                Toolbox toolbox 
    = new Toolbox(this);
                
    this.propertyGridSplitter.Panel1.Controls.Add(toolbox);
                toolbox.Dock 
    = DockStyle.Fill;
                toolbox.BackColor 
    = BackColor;
                toolbox.Font 
    = WorkflowTheme.CurrentTheme.AmbientTheme.Font; 

                WorkflowTheme.CurrentTheme.ReadOnly 
    = false;
                WorkflowTheme.CurrentTheme.AmbientTheme.ShowConfigErrors 
    = false;
                WorkflowTheme.CurrentTheme.ReadOnly 
    = true;

                
    this.propertyGrid.BackColor = BackColor;
                
    this.propertyGrid.Font = WorkflowTheme.CurrentTheme.AmbientTheme.Font;

                AppDomain.CurrentDomain.AssemblyResolve 
    += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
            }


    2.使WorkflowDesignerControl中的工具箱运行时加载Activitie(可以是自定义的)
     在ToolBoxItems.txt中注册
     例如我有个自定义的basic Activitie,如果要把这个Activiti加入工具箱中可以在ToolBoxItems.txt中这样写
       ActivityLibrary.MessageActivity, ActivityLibrary
     运行后就可以看到工具箱中有MessageActivity
    3.在设计器中选择Activity并编辑属性
     在WorkflowDesignerControl.cs中注册事件SelectionChanged
     

    ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;

                        
    if (selectionService != null)
                        
    {
                            selectionService.SelectionChanged 
    += new EventHandler(OnSelectionChanged);
                        }


      实现OnSelectionChanged事件
     

     private void OnSelectionChanged(object sender, EventArgs e)
            
    {
                ISelectionService selectionService 
    = GetService(typeof(ISelectionService)) as ISelectionService;

                
    if (selectionService != null)
                
    {
                    
    this.propertyGrid.SelectedObjects = new ArrayList(selectionService.GetSelectedComponents()).ToArray();
                }

            }


     这样,当WorkflowDesignerControl运行时,在右边下角会显示会选择所选择Activity的属性
    4.使工作流设计器支持删除功能
    在WorkflowDesignerControl.cs中加入方法DeleteSelected,支持在设计器中删除Activity.

    public void DeleteSelected()
            
    {
                ISelectionService selectionService 
    = (ISelectionService)this.GetService(typeof(ISelectionService));

                
    if (selectionService != null)
                
    {
                    
    if (selectionService.PrimarySelection is Activity)
                    
    {
                        Activity activity 
    = (Activity)selectionService.PrimarySelection;

                        
    if (activity.Name != this.WorkflowName)
                        
    {
                            activity.Parent.Activities.Remove(activity);
                            
    this.workflowView.Update();
                        }

                    }

                }

            }
     

           
    在界面工具条上添加Button,属性如下
      Name: btnDelete
     DisplayStyle: Text
     Text: “Remove Activity”
    在click事件中写入对WorkflowDesignerControl中DeleteSelected方法的调用

    private void btnDelete_Click(object sender, EventArgs e)
            
    {
                
    this.workflowDesignerControl.DeleteSelected();
            }

    5.使工作流设计器实现保存,编译,运行和打开已保存工作流的功能。
    在工具条上再次添加按钮名称分别为打开,保存,编译和运行,在这些按钮的事件触发程序中调用workflowDesignerControl中已经定义好的方法
    5.1在workflowDesignerControl中添加方法,加载已经存在的工作流模板文件
      

     public void LoadExistingWorkflow()
            
    {
                OpenFileDialog openFileDialog 
    = new OpenFileDialog();
                openFileDialog.Filter 
    = "xoml files (*.xoml)|*.xoml|All files (*.*)|*.*";
                openFileDialog.FilterIndex 
    = 1;
                openFileDialog.RestoreDirectory 
    = true;

                
    if (openFileDialog.ShowDialog() == DialogResult.OK)
                
    {
                    
    using (XmlReader xmlReader = XmlReader.Create(openFileDialog.FileName))
                    
    {
                        WorkflowMarkupSerializer serializer 
    = new WorkflowMarkupSerializer();
                        
    this.workflow = (SequentialWorkflowActivity)serializer.Deserialize(xmlReader);
                        
    this.LoadWorkflow();

                        
    this.XomlFile = openFileDialog.FileName;
                        
    this.Text = "Designer Hosting Sample -- [" + openFileDialog.FileName + "]";
                    }

                }

            }


    5.2:保存功能实现
     

    private void SaveFile()
            
    {
                
    if (this.XomlFile.Length != 0)
                
    {
                    
    this.SaveExistingWorkflow(this.XomlFile);
                }

                
    else
                
    {
                    SaveFileDialog saveFileDialog 
    = new SaveFileDialog();
                    saveFileDialog.Filter 
    = "xoml files (*.xoml)|*.xoml|All files (*.*)|*.*";
                    saveFileDialog.FilterIndex 
    = 1;
                    saveFileDialog.RestoreDirectory 
    = true;

                    
    if (saveFileDialog.ShowDialog() == DialogResult.OK)
                    
    {
                        
    this.SaveExistingWorkflow(saveFileDialog.FileName);
                        
    this.Text = "Designer Hosting Sample -- [" + saveFileDialog.FileName + "]";
                    }

                }

            }


    5.3:编译功能实现
     

    public bool Compile()
            
    {
                
    return this.Compile(true);
            }


     
    public bool Compile(bool showMessage)
     
    {
         
    if (!this.Save(false))
         
    {
             
    return false;
         }


         
    if (!File.Exists(this.XomlFile))
         
    {
             MessageBox.Show(
    this"Cannot locate xoml file: " + Path.Combine(Path.GetDirectoryName(this.GetType().Assembly.Location), XomlFile), this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
             
    return false;
         }


         
    bool compileOK = true;

         Cursor cursor 
    = this.Cursor;
         
    this.Cursor = Cursors.WaitCursor;

         
    try
         
    {
             
    // Compile the workflow
             String[] assemblyNames = { AdditionalAssembies };
             WorkflowCompiler compiler 
    = new WorkflowCompiler();
             WorkflowCompilerParameters parameters 
    = new WorkflowCompilerParameters(assemblyNames);
             parameters.LibraryPaths.Add(Path.GetDirectoryName(
    typeof(ActivityLibrary.MessageActivity).Assembly.Location));
             parameters.GenerateInMemory 
    = true;
             WorkflowCompilerResults compilerResults 
    = compiler.Compile(parameters, this.XomlFile);

             inMemoryAssembly 
    = compilerResults.CompiledAssembly;

             StringBuilder errors 
    = new StringBuilder();

             
    foreach (CompilerError compilerError in compilerResults.Errors)
             
    {
                 errors.Append(compilerError.ToString() 
    + '\n');
             }


             
    if (errors.Length != 0)
             
    {
                 MessageBox.Show(
    this, errors.ToString(), this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                 compileOK 
    = false;
             }

             
    else if (showMessage)
             
    {
                 MessageBox.Show(
    this"Workflow compiled successfully. Compiled assembly:\n" + compilerResults.CompiledAssembly.GetName(), this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
             }

         }

         
    finally
         
    {
             
    this.Cursor = cursor;
         }


         
    return compileOK;
     }


    注意:
    parameters.GenerateInMemory = true;这时assembly只在内存中生成,不输出到文件
    如果要生成.dll文件,需要修改为
    parameters.GenerateInMemory = false;
    parameters.OutputAssembly = string.Format("{0}.dll", this.WorkflowName);
     
    6:在工具条的事件中调用这些方法
    测试一下
    如果还没有保存,运行后会先保存并编译。

    补传 本文所示代码:demo


         

  • 相关阅读:
    对象,类,封装,继承,多态是什么
    面向对象和非面向对象程序的区别是什么?
    什么是OOA,OOP
    git stash git tag
    从一个远程仓库同步向另一个远程仓库同步代码
    VScode 配置rust开发环境
    IAR ICCARM V8.32.3在Windows Server端进行Ollydbg破解
    阅读笔记
    FP32转FP16能否加速libtorch调用
    阅读笔记-Chained-Tracker
  • 原文地址:https://www.cnblogs.com/lodestar/p/656119.html
Copyright © 2011-2022 走看看