上篇已實現 FTP 下載核心邏輯與依賴屬性,本篇將聚焦於讓自定義活動具備生產級體驗:設計時驗證、視覺化外觀、工具箱圖示與名稱自定義。
工作流設計器會在活動配置不完整時顯示紅色驚嘆號(如未設定 Code 活動的 ExecuteCode)。這背後是 ActivityValidator 在工作:設計器狀態變更或編譯時自動檢查屬性,將錯誤/警告加入集合。
public class FtpGetFileActivityValidator : ActivityValidator {
public override ValidationErrorCollection Validate(ValidationManager manager, object obj) {
FtpGetFileActivity fget = obj as FtpGetFileActivity;
if (null == fget) throw new InvalidOperationException();
ValidationErrorCollection errors = base.Validate(manager, obj);
if (null != fget.Parent) {
// 必塊驗證:FtpUrl
if (String.IsNullOrEmpty(fget.FtpUrl) &&
fget.GetBinding(FtpGetFileActivity.FtpUrlProperty) == null) {
errors.Add(new ValidationError("必須指定 FTP 伺服器 URL(含檔名)", 100, false));
}
// 格式驗證:必須為 FTP URI
Uri tempUri = null;
if (Uri.TryCreate(fget.FtpUrl, UriKind.Absolute, out tempUri)) {
if (tempUri.Scheme != Uri.UriSchemeFtp) {
errors.Add(new ValidationError("FTP URL 必須指向 FTP 端點", 101, false));
}
} else if (!String.IsNullOrEmpty(fget.FtpUrl)) {
errors.Add(new ValidationError("FTP URL 格式無效", 102, false));
}
// 選填提示:FtpUser / FtpPassword
if (String.IsNullOrEmpty(fget.FtpUser) &&
fget.GetBinding(FtpGetFileActivity.FtpUserProperty) == null) {
errors.Add(new ValidationError("將使用匿名帳號登入 FTP 伺服器", 200, true));
}
if (String.IsNullOrEmpty(fget.FtpPassword) &&
fget.GetBinding(FtpGetFileActivity.FtpPasswordProperty) == null) {
errors.Add(new ValidationError("將使用預設匿名密碼 'someone@example.com'", 300, true));
}
}
return errors;
}
}
註冊驗證器:在活動類別加上 [ActivityValidator(typeof(FtpGetFileActivityValidator))]。
FtpImage.bmp 加入專案,設定「建置動作」為「內嵌資源」[ToolboxBitmap(typeof(FtpGetFileActivity), "FtpImage.bmp")][ActivityDesignerThemeAttribute(typeof(FtpGetFileActivityDesignerTheme))]
public class FtpGetFileActivityDesigner : ActivityDesigner { }
internal sealed class FtpGetFileActivityDesignerTheme : ActivityDesignerTheme {
public FtpGetFileActivityDesignerTheme(WorkflowTheme theme) : base(theme) {
this.BorderColor = Color.Black;
this.BorderStyle = DashStyle.Solid;
this.BackColorStart = Color.Silver;
this.BackColorEnd = Color.LightBlue;
this.BackgroundStyle = LinearGradientMode.Horizontal;
}
}
註冊設計器:[Designer(typeof(FtpGetFileActivityDesigner), typeof(IDesigner))]。活動將以銀→淺藍水平漸層、實心黑框呈現。
預設工具箱使用類別名稱。透過 ActivityToolboxItem 衍生類別可自訂:
[Serializable]
class FtpGetFileActivityToolboxItem : ActivityToolboxItem {
public FtpGetFileActivityToolboxItem() { InitializeComponent(); }
public FtpGetFileActivityToolboxItem(Type type) : base(type) { InitializeComponent(); }
private FtpGetFileActivityToolboxItem(SerializationInfo info, StreamingContext context) {
Deserialize(info, context); InitializeComponent();
}
protected void InitializeComponent() { this.DisplayName = "FTP File Get"; }
}
註冊:[ToolboxItem(typeof(FtpGetFileActivityToolboxItem))]。
GrabberFlow,拖入 FtpGetFileActivityFtpUrl、FtpUser、FtpPassword),自動消除驗證錯誤FtpActivity.dll,即可看到自定義圖示與「FTP File Get」名稱Form1.cs 中啟動工作流實例,傳入參數字典本篇示範基本活動。組合活動(如 IfElse)需額外處理子活動預填充,可參考 MSDN 範例 ParallelIf 活動。