作者Cathy Dumas ,Workflow Designer团队的一个程序经理。
原文地址:http://blogs.msdn.com/cathyk/archive/2009/11/12/expressiontextbox-101.aspx
ExpressionTextBox是我们在自定义活动设计器中编辑表达式的基本构造块。 如果您正在编写一个自定义活动设计器并且使用了表达式,您将会使用此控件。 这篇文章的目的是为了给自定义活动设计器开发人员一个概述。 我会对SDK的例子做少量的解释并一步一步深入。要想跳过这篇文章你只要看下SDK中的例子ExpressionTextBoxSample就可以了。
开始设计一个活动设计器,首先要引入下面的命名空间:
<sap:ActivityDesigner x:Class="Microsoft.Samples.ExpressionTextBoxSample.MultiAssignDesigner"
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:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation">
表达式绑定到参数要使用ArgumentToExpressionConverter,该类位于System.Activities.Presentation.Converters命名空间中。将此转换器加入到你的资源字典中,如下所示:
<sap:ActivityDesigner.Resources>
<ResourceDictionary>
<sapc:ArgumentToExpressionConverter x: Key="ArgumentToExpressionConverter" />
</ResourceDictionary>
</sap:ActivityDesigner.Resources>
现在你可以继续添加你的ExpressionTextBox。 首先,你需要确定你所编辑的是哪种类型的表达式。 您可以在ExpressionTextBox中编辑两种类型的表达式,location expressions ( L-value expressions) 和 value expressions.。 value expressions的计算结果为一个的值的表达式,可以将它们放在赋值语句的右侧, InArguments 对应值的表达式,它们被序列化为 VisualBasicValue 表达式 现在我们假设有一个 String 类型的 名为FooValue 的 InArgument 的活动。 下面是一个简单的绑定到该参数的ExpressionTextBox:
<sapv:ExpressionTextBox
Expression="{Binding Path=ModelItem.FooValue, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In }"
ExpressionType="s:String"
OwnerActivity="{Binding Path=ModelItem}" />
Expression和OwnerActivity是必须要设置的,ExpressionType的设置也很重要,否则会有一些不稳定的行为。Path是你要绑定的参数,Mode一般都设置为TwoWay,然后我们将 In 参数传递给ArgumentToExpressionConverter告诉我们绑定到一个 InArgument。
反之,location expressions对应于OutArguments,它们被序列化为 VisualBasicReference 表达式 。你可以将location expressions放在赋值语句左侧。现在我们假设有一个 String 类型的名为FooReference 的 OutArgument 的活动。下面是一个简单的绑定到该参数的ExpressionTextBox:
<sapv:ExpressionTextBox
Expression="{Binding Path=ModelItem.FooReference, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=Out }"
OwnerActivity="{Binding Path=ModelItem}"
ExpressionType="s:String"
UseLocationExpression="True" />
前面的示例中有两个差异。 由于我们绑定到L-value expression,UseLocationExpression 属性设置为 True。 因为我们绑定到一个 OutArgument, ConverterParameter 为Out。
还有一点我会放到另一篇文章中,绑定 ExpressionTextBoxes 到CLR 属性和绑定到 untyped 参数。
译者注:
1. ArgumentToExpressionConverter是当绑定表达式到参数时的类型转换器。 ConverterParameter只支持In, Out不支持InOut。
2. UseLocationExpression 属性用在OutArguments 来指定L-value (“left value” 或 “location value”) 表达式时。
下面是作者文中提到的SDK中的例子,例子中开发了一个自定义的MultiAssign活动。
1.xaml如下:
<sad:ActivityDesigner x:Class="Microsoft.Samples.ExpressionTextBoxSample.MultiAssignDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sad="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sadv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:sadc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation">
<sad:ActivityDesigner.Resources>
<ResourceDictionary>
<sadc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
</ResourceDictionary>
</sad:ActivityDesigner.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<sadv:ExpressionTextBox
HintText="To"
Expression="{Binding Path=ModelItem.To1, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=Out }"
OwnerActivity="{Binding Path=ModelItem}"
UseLocationExpression="True"
Width="110"
Margin="0,5"
Grid.Row="0"
Grid.Column="0"
MaxLines="1" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="=" Grid.Row ="0" Grid.Column="1"/>
<sadv:ExpressionTextBox
Expression="{Binding Path=ModelItem.Value1, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In }"
OwnerActivity="{Binding Path=ModelItem}"
Width="110"
Margin="0,5"
Grid.Row="0"
Grid.Column="2"
MaxLines="1" />
<sadv:ExpressionTextBox
HintText="To"
Expression="{Binding Path=ModelItem.To2, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=Out }"
OwnerActivity="{Binding Path=ModelItem}"
UseLocationExpression="True"
Width="110"
Margin="0,5"
Grid.Row="1"
Grid.Column="0"
MaxLines="1" />
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="=" Grid.Row ="1" Grid.Column="1"/>
<sadv:ExpressionTextBox
Expression="{Binding Path=ModelItem.Value2, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In }"
OwnerActivity="{Binding Path=ModelItem}"
Width="110"
Margin="0,5"
Grid.Row="1"
Grid.Column="2"
MaxLines="1" />
</Grid>
</sad:ActivityDesigner>
3. 如下图:
4. 代码如下:
[Designer(typeof(MultiAssignDesigner))]
public sealed class MultiAssign : CodeActivity
{
[DefaultValue((string)null), RequiredArgument]
public OutArgument To1 { get; set; }
public OutArgument To2 { get; set; }
[DefaultValue((string)null), RequiredArgument]
public InArgument Value1 { get; set; }
public InArgument Value2 { get; set; }
protected override void Execute(CodeActivityContext context)
{
// Obtain the runtime value of the arguments
this.To1.Set(context, this.Value1.Get(context));
this.To2.Set(context, this.Value2.Get(context));
}
}