Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Workflow 将数据绑定到自定义活动设计器中的组合框_Workflow_Workflow Foundation_Workflow Foundation 4 - Fatal编程技术网

Workflow 将数据绑定到自定义活动设计器中的组合框

Workflow 将数据绑定到自定义活动设计器中的组合框,workflow,workflow-foundation,workflow-foundation-4,Workflow,Workflow Foundation,Workflow Foundation 4,我有一个自定义活动,其中有一个in参数是字符串。但是,我不希望设计器输入任意字符串,而是希望设计器显示一个带有选项列表的组合框,这些选项是动态的,并且从数据库加载到列表集合中 我的问题是,我不知道如何将设计器中的组合框绑定到此列表,并将选择设置为活动的in参数。视觉上,我让活动设计器工作,这只是这一步。通常,我会使用属性编写活动,而不是不一致的。这简化了场景: <ComboBox ItemsSource="{Binding Path=ValidOptions}" SelectedVal

我有一个自定义活动,其中有一个in参数是字符串。但是,我不希望设计器输入任意字符串,而是希望设计器显示一个带有选项列表的组合框,这些选项是动态的,并且从数据库加载到列表集合中


我的问题是,我不知道如何将设计器中的组合框绑定到此列表,并将选择设置为活动的in参数。视觉上,我让活动设计器工作,这只是这一步。

通常,我会使用
属性编写活动,而不是
不一致的
。这简化了场景:

<ComboBox ItemsSource="{Binding Path=ValidOptions}" 
 SelectedValue="{Binding Path=ModelItem.MyStringProperty, Mode=TwoWay}"/>
)


如果将
inarument
添加到混合中,您将遇到的问题是组合框中的字符串值不能直接分配给
ModelItem
预期的
inarument
。在绑定中使用自定义的
IValueConverter
可以解决此问题。

解决此问题的一种方法是定义您自己的ComboBoxEditor,它派生自UITypeEditor。 在活动类中公开要绑定此组合框的集合,并使用以下属性装饰活动类中的可绑定属性:

[EditorAttribute(typeof(CustomListBoxEditor), typeof(System.Drawing.Design.UITypeEditor))]
此外,在自定义comboboxEditor中,您还必须修改
EditValue(ITypeDescriptorContext上下文、IServiceProvider提供程序、对象值)方法获取集合并将其绑定到组合框。

前面的答案很有用,但对我来说还不够。最终,我在微软的.NET4.5开发者指南中找到了一篇来自2012年的精彩文章:。这篇文章几乎是完整的答案——除了自定义转换器类中的一个小错误和一个主要缺陷:该技术将从组合框中保存一个值,但当您重新打开工作流时,它不会恢复该值

微软的Ron Jacobs为定制活动设计师设计。我最终将两者结合起来,得到了一个有效的解决方案

定制设计师

ModelToObjectValueConverter
是一个非常有用的资源,允许我跳过创建自己的
IValueConverter
。在
ObjectDataProvider
中,您可以看到我通过调用静态方法
People.GetPeople()
加载字符串列表。ComboBox作为项目源绑定到该提供程序,但将所选值绑定到自定义活动的Person属性(如下所示)

工作流

现在,可以将自定义活动
CodeActivity1
拖到工作流上。进行选择时,选定的值将显示在“属性”窗格中。保存工作流。关闭并重新打开。以前选择的值将根据需要保留


您真的希望您的自定义活动有一个无担保而不是属性吗?(public-inagrament Arg{get;set;}vs.public-string Arg{get;set;})@Tim,我想只要一个标准属性也可以。@Tim,很抱歉花了这么长时间才回来,这是忙碌的一周,我甚至没有机会测试这一点来确认我理解并且这符合我正在尝试做的事情。一旦我这样做了,我就会回来,要么标记为已回答,要么进一步探索你和社区的大脑!谢谢
[EditorAttribute(typeof(CustomListBoxEditor), typeof(System.Drawing.Design.UITypeEditor))]
<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>
[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);    
    }
}