例如,我要实现一个BxFindNumber组件,它有一个集合,是List {3, 4, 7, 8},我们的组件遍历所有元素,当自定义活动返回true时,停止遍历,逻辑代码如下:
[Designer(typeof(FindNumberView))]
public sealed class BxFindNumer : NativeActivity<string>, IActivityTemplateFactory
{
private List<int> list = new List<int>() { 3, 4, 7, 8 };
private Variable<IEnumerator<int>> listEnumerator;
private CompletionCallback<bool> onChildComplete;
[Browsable(false)]
public ActivityFunc<int, bool> Body { get; set; }
private CompletionCallback<bool> OnChildComplete
{
get
{
if (this.onChildComplete == null)
{
this.onChildComplete = new CompletionCallback<bool>(this.getStateAndExecute);
}
return this.onChildComplete;
}
}
public BxFindNumer()
{
this.listEnumerator = new Variable<IEnumerator<int>>();
}
public Activity Create(DependencyObject target)
{
return new BxFindNumer()
{
Body = new ActivityFunc<int, bool>()
{
Argument = new DelegateInArgument<int>() { Name = "n1" },
Result = new DelegateOutArgument<bool> { Name = "r" },
Handler = new Sequence()
}
};
}
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.AddDelegate(this.Body);
metadata.AddImplementationVariable(this.listEnumerator);
base.CacheMetadata(metadata);
}
protected override void Execute(NativeActivityContext context)
{
IEnumerator<int> enumerator = this.list.GetEnumerator();
this.listEnumerator.Set(context, enumerator);
if (this.Body == null || this.Body.Handler == null)
{
enumerator.Dispose();
}
else
{
internalExecute(context, null, enumerator);
}
}
private void internalExecute(NativeActivityContext context, ActivityInstance completedInstance,
IEnumerator<int> listEnumerator)
{
if (!listEnumerator.MoveNext())
{
if (completedInstance != null && (completedInstance.State == ActivityInstanceState.Canceled || context.IsCancellationRequested && completedInstance.State == ActivityInstanceState.Faulted))
{
context.MarkCanceled();
}
listEnumerator.Dispose();
}
else if (context.IsCancellationRequested)
{
context.MarkCanceled();
listEnumerator.Dispose();
}
else
{
int val = listEnumerator.Current;
context.ScheduleFunc(this.Body, val, this.OnChildComplete);
}
}
private void getStateAndExecute(NativeActivityContext context, ActivityInstance completedInstance, bool result)
{
if (! result)
{
IEnumerator<int> listEnumerator = this.listEnumerator.Get(context);
this.internalExecute(context, null, listEnumerator);
}
else
{
Console.WriteLine("结束执行");
}
}我们的组件实现了IActivityTemplateFactory,它定义了ActivityFunc<int, bool>的输入参数n1,返回参数r,委托主体时一个Sequence对象:
public Activity Create(DependencyObject target)
{
return new BxFindNumer()
{
Body = new ActivityFunc<int, bool>()
{
Argument = new DelegateInArgument<int>() { Name = "n1" },
Result = new DelegateOutArgument<bool> { Name = "r" },
Handler = new Sequence()
}
};
}这样,我们在前台,可以使用n1来获取当前遍历值,我们通过把r设为true来停止遍历:
private void internalExecute(NativeActivityContext context, ActivityInstance completedInstance,
IEnumerator<int> listEnumerator)
{
if (!listEnumerator.MoveNext())
{
if (completedInstance != null && (completedInstance.State == ActivityInstanceState.Canceled || context.IsCancellationRequested && completedInstance.State == ActivityInstanceState.Faulted))
{
context.MarkCanceled();
}
listEnumerator.Dispose();
}
else if (context.IsCancellationRequested)
{
context.MarkCanceled();
listEnumerator.Dispose();
}
else
{
int val = listEnumerator.Current;
context.ScheduleFunc(this.Body, val, this.OnChildComplete);
}
}
private void getStateAndExecute(NativeActivityContext context, ActivityInstance completedInstance, bool result)
{
if (! result)
{
IEnumerator<int> listEnumerator = this.listEnumerator.Get(context);
this.internalExecute(context, null, listEnumerator);
}
else
{
Console.WriteLine("结束执行");
}
}它的视图代码如下:
<sap:ActivityDesigner x:Class="FindNumer.FindNumberView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:sadc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sap:ActivityDesigner.Resources>
<sadc:ArgumentToExpressionConverter x:Key="argConverter"></sadc:ArgumentToExpressionConverter>
<DataTemplate x:Key="Collapsed">
<StackPanel>
<TextBlock><Run Text="FindNumberView"/></TextBlock>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="Expanded">
<StackPanel MinWidth="250" MaxWidth="850">
<StackPanel Orientation="Horizontal" Margin="0,10,0,0" MinWidth="400">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,0,0" LineHeight="20">当前值</TextBlock>
<TextBox Name="directoryPathBox" x:Uid="directoryPathBox" AutomationProperties.Name="directory"
AutomationProperties.AutomationId="ArgumentName1" HorizontalAlignment="Stretch"
VerticalAlignment="Center" TextBlock.LineHeight="20" MinWidth="100" MaxLength="10"
Text="{Binding Path=ModelItem.Body.Argument.Name, Mode=TwoWay, ValidatesOnExceptions=true}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="20,0,0,0" LineHeight="20">是否已找到</TextBlock>
<TextBox Name="filePathBox" x:Uid="filePathBox" AutomationProperties.Name="file"
AutomationProperties.AutomationId="ArgumentName2" HorizontalAlignment="Stretch"
VerticalAlignment="Center" TextBlock.LineHeight="20" MinWidth="100" MaxLength="10"
Text="{Binding Path=ModelItem.Body.Result.Name, Mode=TwoWay, ValidatesOnExceptions=true}" />
</StackPanel>
</StackPanel>
<sap:WorkflowItemPresenter x:Uid="sad:WorkflowItemPresenter_1" AutomationProperties.AutomationId="Activity"
IsDefaultContainer="true" HintText="把活动添加到这里"
AllowedItemType="{x:Type sa:Activity}" MinWidth="100" MinHeight="100"
Item="{Binding Path=ModelItem.Body.Handler, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
<Style x:Key="ExpandOrCollapsedStyle" TargetType="{x:Type ContentPresenter}">
<Setter Property="ContentTemplate" Value="{DynamicResource Collapsed}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShowExpanded}" Value="true">
<Setter Property="ContentTemplate" Value="{DynamicResource Expanded}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</sap:ActivityDesigner.Resources>
<Grid>
<ContentPresenter Style="{DynamicResource ExpandOrCollapsedStyle}" Content="{Binding}" />
</Grid>
</sap:ActivityDesigner>