我有一个自定义活动,其中一个 in 参数是一个字符串。但是,我不想让设计人员输入任意字符串,而是希望设计人员看到一个带有选项列表的组合框,这些选项是动态的,并且从数据库加载到 List<> 集合中。
我的问题是我不知道如何将设计器中的组合框绑定到此列表并将选择设置为活动的 in 参数。从视觉上看,我让活动设计器工作,这只是这一步。
我有一个自定义活动,其中一个 in 参数是一个字符串。但是,我不想让设计人员输入任意字符串,而是希望设计人员看到一个带有选项列表的组合框,这些选项是动态的,并且从数据库加载到 List<> 集合中。
我的问题是我不知道如何将设计器中的组合框绑定到此列表并将选择设置为活动的 in 参数。从视觉上看,我让活动设计器工作,这只是这一步。
通常,我会用 aproperty
而不是InArgument
. 这简化了场景:
<ComboBox ItemsSource="{Binding Path=ValidOptions}"
SelectedValue="{Binding Path=ModelItem.MyStringProperty, Mode=TwoWay}"/>
(这里 ValidOptions 是 ActivityDesigner 类的一些 Collection 属性。MyStringProperty 是底层活动的一些公共 get/set/ 属性,例如:
public string MyStringProperty { get; set; }
)
如果您添加InArgument
到组合中,您将遇到的问题是组合框中的字符串值不能直接分配给ModelItem
expecting InArgument<string>
。这可以IValueConverter
在您的绑定中使用自定义来修复。
The previous answers are helpful but were not enough for me. Eventually I found a terrific article from 2012, in Microsoft's .Net 4.5 Developer Guide: Binding a custom activity property to a designer control. That article was almost the full answer - except for a minor bug in the custom converter class, and a major flaw: that technique will save a value from the ComboBox, but it will not restore it when you re-open your workflow.
Microsoft's Ron Jacobs has another answer for custom activity designers. I ended up combining the two to get a working solution.
Custom Designer
The ModelToObjectValueConverter
was an incredibly helpful resource, allowing me to skip creating my own IValueConverter
. In the ObjectDataProvider
you see me loading a list of strings by calling a static method, People.GetPeople()
. The ComboBox binds to that provider as the item source, but binds the selected value to the Person property on the custom Activity (below)
<sap:ActivityDesigner x:Class="ActivityLibrary1.ComboBoxActivityDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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"
xmlns:c="clr-namespace:ActivityLibrary1">
<sap:ActivityDesigner.Resources>
<ResourceDictionary>
<sapc:ModelToObjectValueConverter x:Key="ModelToObjectValueConverter" />
<ObjectDataProvider x:Key="people" ObjectType="{x:Type c:People}" MethodName="GetPeople"/>
</ResourceDictionary>
</sap:ActivityDesigner.Resources>
<Grid>
<Label Content="Person" HorizontalAlignment="Left" VerticalAlignment="Top" />
<ComboBox HorizontalAlignment="Left"
Margin="66,0,0,0"
VerticalAlignment="Top"
Width="120"
SelectedValue="{Binding Path=ModelItem.Person, Mode=TwoWay, Converter={StaticResource ModelToObjectValueConverter} }"
ItemsSource="{Binding Source={StaticResource people}}">
</ComboBox>
</Grid>
</sap:ActivityDesigner>
Custom Code Activity
Note that this uses a property rather than an InArgument, which makes binding the ComboBox easier.
[Designer(typeof(ComboBoxActivityDesigner))]
public class CodeActivity1 : CodeActivity
{
public string Person { get; set; }
protected override void Execute(CodeActivityContext context)
{
// Just to demonstrate that it worked
MessageBox.Show(Person);
}
}
Workflow
Now the custom activity, CodeActivity1
, can be dragged onto a workflow. When you make a selection, the selected value will appear in the properties pane. Save the workflow. Close and re-open. The previously-selected value will persist as desired.
解决它的一种方法是定义您自己的从 UITypeEditor 派生的 ComboBoxEditor。在活动类中公开您要绑定此组合框的集合,并使用以下属性在活动类中装饰您的可绑定属性:
[EditorAttribute(typeof(CustomListBoxEditor), typeof(System.Drawing.Design.UITypeEditor))]
同样在自定义组合框编辑器中,您必须修改您的 EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 方法以获取集合并将其绑定到组合框。