2011-05-09 48 views
5

我在驗證在設計器中爲自定義活動正常工作時遇到問題。重現行爲的最簡單的示例如下:自定義活動設計器中的參數驗證

我有存儲在一個字典參數的動態集合的自定義WF4活動:

[Designer(typeof(DictionaryActivityDesigner))] 
public class DictionaryActivity : NativeActivity 
{ 
    [Browsable(false)] 
    public Dictionary<string, InArgument> Arguments { get; set; } 
    public InArgument<string> StringArg { get; set; } 

    public DictionaryActivity() 
    { 
     Arguments = new Dictionary<string, InArgument>(); 
    } 

    protected override void Execute(NativeActivityContext context) 
    { } 
} 

在設計師,我dinamically創建編輯表達式文本框這些論點。用戶必須限定在一個單獨的模式窗口的參數和它們的類型的可能性,但爲了簡單起見,我有固定的這個樣品中的參數:

public partial class DictionaryActivityDesigner 
{ 
    private Dictionary<string, Type> definition; 

    public DictionaryActivityDesigner() 
    { 
     definition = new Dictionary<string, Type> 
     { 
      { "String Arg", typeof(string) }, 
      { "Int Arg", typeof(int) } 
     }; 

     InitializeComponent(); 
    } 

    public void InitializeGrid(Dictionary<string, Type> arguments) 
    { 
     ArgumentsGrid.RowDefinitions.Clear(); 
     ArgumentsGrid.Children.Clear(); 

     int gridRow = 0; 
     foreach (var arg in arguments) 
     { 
      ArgumentsGrid.RowDefinitions.Add(new RowDefinition()); 

      var label = new Label() 
      { 
       Content = arg.Key + ":" 
      }; 
      Grid.SetRow(label, gridRow); 
      Grid.SetColumn(label, 0); 
      ArgumentsGrid.Children.Add(label); 

      var textbox = new ExpressionTextBox() 
      { 
       ExpressionType = arg.Value, 
       OwnerActivity = ModelItem, 
       UseLocationExpression = false 
      }; 
      var binding = new Binding() 
      { 
       Mode = BindingMode.TwoWay, 
       Converter = new ArgumentToExpressionConverter(), 
       ConverterParameter = "In", 
       Path = new PropertyPath("ModelItem.Arguments[(0)]", arg.Key) 
      }; 
      textbox.SetBinding(ExpressionTextBox.ExpressionProperty, binding); 
      Grid.SetRow(textbox, gridRow); 
      Grid.SetColumn(textbox, 1); 
      ArgumentsGrid.Children.Add(textbox); 

      gridRow++; 
     } 
    } 

    private void ActivityDesigner_Loaded(object sender, RoutedEventArgs e) 
    { 
     InitializeGrid(definition); 
    } 
} 

下面是設計者的XAML:

<sap:ActivityDesigner x:Class="ActivityValidation.DictionaryActivityDesigner" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:s="clr-namespace:System;assembly=mscorlib" 
         xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation" 
         xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation" 
         xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation" 
         Loaded="ActivityDesigner_Loaded"> 
    <sap:ActivityDesigner.Resources> 
     <ResourceDictionary> 
      <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" /> 
     </ResourceDictionary> 
    </sap:ActivityDesigner.Resources> 
    <StackPanel Orientation="Vertical"> 
     <Grid Name="ArgumentsGrid"> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition/> 
       <ColumnDefinition MinWidth="250" /> 
      </Grid.ColumnDefinitions> 
     </Grid> 
     <sapv:ExpressionTextBox ExpressionType="s:String" 
           OwnerActivity="{Binding ModelItem}" 
           Expression="{Binding ModelItem.StringArg, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" /> 
    </StackPanel> 
</sap:ActivityDesigner> 

InitializeGrid方法將參數的表達式文本框添加到ArgumentGrid。在它下面,我有一個單獨的靜態定義表達式文本框,用於演示活動中的固定參數以演示(幾乎)所需的行爲。

現在的問題:

  1. 無效表達式的動態參數只能導致錯誤的圖標來顯示文本框旁邊,但它不會傳播到因爲它如果設計師的頂欄靜態定義的文本框中有錯誤。

  2. 如果我在這種無效狀態下關閉設計器(並保存定義),即使錯誤只出現在動態文本框中,eror圖標也會正確傳播到頂部欄。儘管之後的行爲會變得更加奇怪。更改參數的值後,現在即使文本框旁邊的錯誤圖標也不再一致。

  3. 如果我刪除一個動態文本框完全,在字典中的值被設置爲空在工作流定義,其表現爲<x:Null x:Key="String Arg" />,而不是<InArgument x:TypeArguments="x:String" x:Key="String Arg">["a"]</InArgument>或只是ommiting的條目是編輯表達式之前的情況下的內容首次。如果我重新打開這樣的工作流程,即使靜態創建的文本框不能再正常工作(錯誤圖標僅在文本框聚焦時纔可見,並且不會再傳播到頂部)。

看起來很明顯,我在創建動態文本框時做了一些錯誤。什麼是正確的做法?是否有任何示例可用於使用動態數量的參數爲自定義活動創建設計器?

編輯:

對於那些有興趣:

+0

等一下,你不是在每次調用CacheMetadata時都進行驗證嗎?這是關於您可以對活動進行驗證並將錯誤/警告傳播到工作流程的唯一地方。 – Will 2011-05-10 14:47:55

+0

@我可以在CacheMetadata中添加驗證錯誤和警告,但是ExpressionTextBox具有自己的內置驗證,如果輸入的表達式無效,將在文本框旁邊顯示錯誤圖標。我不想重新實現驗證,我不知道如何從CacheMetadata中訪問驗證功能,通過添加驗證錯誤來自行傳播驗證功能。此外:傳播似乎工作得很好,只要我避免收集參數。 – 2011-05-10 19:45:17

回答

4

我遇到了我在這裏描述的問題,同時嘗試爲活動中的動態參數集合創建一個設計器。我設法通過使用內置的DynamicArgumentDialog窗口來解決這個問題。我不得不調整自己的行爲接受的輸入和輸出參數的單個集合:

public Dictionary<string, Argument> Arguments { get; set; } 

,而不是我用的是前兩個單獨集合:

public Dictionary<string, InArgument> InArguments { get; set; } 
public Dictionary<string, OutArgument> OutArguments { get; set; } 

我發現Custom Activity to Invoke XAML Based Child Workflows非常有幫助製作時這項工作。