經常有童鞋在群裡面問同樣一個問題:如何自定義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.Ac tivities.Presentation"
xmlns:sap="clr- namespace:System.Activities.Presentation;assembly=System.Activities.Pr esentation"
xmlns:sapv="clr- namespace:System.Activities.Presentation.View;assembly=System.Activiti es.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就好了呀!自定義活動的外觀 的好處是使流程設計器上更加直觀。只有很直觀了,我們的流程設計器才能拿給 普通用戶使用。
本文配套源碼