自定义工作流活动的外观的两种方式


经常有童鞋在群里面问同样一个问题:如何自定义WF4.0活动的外观。其实一共有两种方式去实现自定义WF4.0活动的外观:一种方式我在以前的博文上实现过,见:WF4.0实战(十一):邮件通知;另外一种方式我将在这里讲述它的实现。故这篇文章中,我将分别用这两种方式去一个最简单的WF4.0自定义活动外观的例子。

  第一种方式:使用[Designer]属性。命名空间为:using System.ComponentModel;代码如下:

[Designer(typeof(CustomWriteLineDesigner))] 
public sealed class CustomWriteLine : CodeActivity 
{ 
  [RequiredArgument] 
  public InArgument<string> Text { get; set; } 
 
  protected override void Execute(CodeActivityContext context) 
  { 
    Console.WriteLine(context.GetValue(this.Text)); 
  } 
}

  上面代码中的CustomWriteLineDesigner是自定义外观的XAML文件。第一种方式代码还可以这样写:

[ ("MyActivityDesigner.CustomWriteLineDesigner,MyActivityDesigner")] 
 public sealed class CustomWriteLine : CodeActivity 
 { 
   [RequiredArgument] 
   public InArgument<string> Text { get; set; } 
 
   protected override void Execute(CodeActivityContext context) 
   { 
     Console.WriteLine(context.GetValue(this.Text)); 
   } 
 }

  CustomWriteLineDesigner的代码如下:

<sap:ActivityDesigner x:Class="MyActivityDesigner.CustomWriteLineDesigner" 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:sadc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation" 
  xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation" 
  xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"> 
  <sap:ActivityDesigner.Resources> 
    <sadc:ArgumentToExpressionConverter x:Key="argConverter"/> 
  </sap:ActivityDesigner.Resources> 
  <sap:ActivityDesigner.Icon> 
    <DrawingBrush> 
      <DrawingBrush.Drawing> 
        <ImageDrawing> 
          <ImageDrawing.Rect> 
            <Rect Location="0,0" Size="16,16" ></Rect> 
          </ImageDrawing.Rect> 
          <ImageDrawing.ImageSource> 
            <BitmapImage UriSource="WriteLine.jpg" ></BitmapImage> 
          </ImageDrawing.ImageSource> 
        </ImageDrawing> 
      </DrawingBrush.Drawing> 
    </DrawingBrush> 
  </sap:ActivityDesigner.Icon> 
  <Grid > 
    <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
 
    <TextBlock Text="Text " Padding="0,2,4,2"/> 
    <sapv:ExpressionTextBox MaxLines="1" Grid.Column="1" Width="200" 
                  Expression="{Binding Path=ModelItem.Message, Mode=TwoWay, Converter={StaticResource argConverter}, ConverterParameter=In}" 
                  OwnerActivity="{Binding Path=ModelItem}" /> 
  </Grid> 
</sap:ActivityDesigner> 
效果:

  以上是第一种方式,如果有不清楚的地方可以参考:WF4.0实战(十一):邮件通知

  第二种方式:代码关联去实现

  上面的方式是硬编码实现的,有些不够灵活,微软内置的活动是采用第二种方式,而不是第一种方式。下面我将一步一步教你如何用第二种方式去实现同样的效果。

  新建一ActivityLibrary项目命名为:MyActivityDesignerTwo,新建一个 ActivityDesignerLibrary项目命名为MyActivityDesignerTwo.Design。从命名上可以看出,MyActivityDesignerTwo用于实现后台的逻辑代码。MyActivityDesignerTwo.Design用于实现自定义活动的UI。项目结构如下图所示:

  其中CustomWriteLineDesigner.xaml代码和第一种方式相同。不同的是多出了一个 DesignerMetadata.cs,CustomWriteLine.cs中去掉了Designer属性的代码,去掉了Designer属性的 CustomWriteLine代码如下:

public sealed class CustomWriteLine : CodeActivity 
{ 
  [RequiredArgument] 
  public InArgument<string> Text { get; set; } 
 
  protected override void Execute(CodeActivityContext context) 
  { 
    Console.WriteLine(context.GetValue(this.Text)); 
  } 
}

  DesignerMetadata.cs的代码如下:

public class DesignerMetadata : IRegisterMetadata 
{ 
  /// <summary> 
  /// Register the designer for the write line activity 
  /// </summary> 
  public void Register() 
  { 
    AttributeTableBuilder builder = new AttributeTableBuilder(); 
 
    Type t = typeof(CustomWriteLine); 
 
    builder.AddCustomAttributes(t, new DesignerAttribute(typeof(CustomWriteLineDesigner))); 
 
    MetadataStore.AddAttributeTable(builder.CreateTable()); 
  } 
}

  后台的代码和UI的设计并不在同一个项目中,我们如何将他们关联起来呢?很简单,我们只要将两个项目生成的dll放在同一个目录下面就OK了。我们修改MyActivityDesignerTwo.Design的生成路径。如下图:

  新建一个测试的WorkflowConsoleApplication项目,在这个项目中添加MyActivityDesignerTwo引用。

  我们将微软内置的WriteLine和刚才定义的活动做个比较,如下图:

  你会发现有一个明显不同的地方:我们自定义的活动比微软内置的活动要宽一些。Text属性上我们自定义的WriteLine活动上显示全部的文字:"这个我们自定义的WriteLine活动",而内置的活动隐藏了部分文字没有显示。这一点的是蛮有好处的:在流程设计器上自定义的活动比内置的活动更加直观。

  总结:这篇文章教你用两种方式去实现自定义活动的外观。有人可能会问为什么要自定义活动的外观,一个CustomWriteLine就好了呀!自定义活动的外观的好处是使流程设计器上更加直观。只有很直观了,我们的流程设计器才能拿给普通用户使用

本文示例源代码或素材下载


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3