自定义活动设计器中的参数验证

2024-02-17

我在验证自定义活动的设计器中正常工作时遇到问题。重现该行为的最简单示例如下:

我有一个自定义 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)
    { }
}

在设计器中,我动态地创建表达式文本框来编辑这些参数。用户可以在单独的模式窗口中定义参数及其类型,但为了简单起见,我已修复此示例中的参数:

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>

The InitializeGrid方法将参数的表达式文本框添加到ArgumentGrid。在它下面,我有一个单独的静态定义表达式文本框,用于活动中的固定参数,以演示(几乎)所需的行为。

现在针对问题:

  1. 动态参数的无效表达式只会导致错误图标出现在文本框旁边,但不会像静态定义的文本框中存在错误时那样传播到设计器的顶部栏。

  2. 如果我在这种无效状态下关闭设计器(并保存定义),即使错误仅出现在动态文本框中,错误图标也会正确传播到顶部栏。尽管之后行为变得更加奇怪。更改参数的值后,现在即使文本框旁边的错误图标也不再一致工作。

  3. 如果我完全删除动态文本框的内容,字典中的值将设置为 null,这在工作流定义中表现为<x:Null x:Key="String Arg" />代替<InArgument x:TypeArguments="x:String" x:Key="String Arg">["a"]</InArgument>或者像第一次编辑表达式之前一样省略条目。如果我重新打开这样的工作流程,即使静态创建的文本框也无法再正常工作(错误图标仅在文本框聚焦时才可见,并且不再传播到顶部)。

很明显,我在创建动态文本框时做错了什么。正确的做法是什么?是否有任何示例可用于为具有动态参数数量的自定义活动创建设计器?

EDIT:

对于那些感兴趣的人:

  • MSDN 论坛上还有一些更多讨论,我也在那里发布了问题 http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/037c0e00-1003-4f3a-a4a7-d30b2556371b.
  • 作为讨论的结果,我还提交了关于 Microsoft Connect 的报告 https://connect.microsoft.com/wf/feedback/details/671678/argument-validation-in-custom-activity-designer.

我在尝试为活动中的动态参数集合创建设计器时遇到了此处描述的问题。我设法通过使用内置的方法解决了这个问题动态参数对话框 http://msdn.microsoft.com/en-us/library/system.activities.presentation.dynamicargumentdialog.aspx窗户。我必须重组我的活动以接受输入和输出参数的单个集合:

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

而不是我之前使用的两个单独的集合:

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

我找到了用于调用基于 XAML 的子工作流的自定义活动 http://code.msdn.microsoft.com/WF4-Custom-Activity-to-f7c9b0fc进行这项工作时非常有帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义活动设计器中的参数验证 的相关文章

随机推荐