在 WF 重新托管调试界面中使用实例作为 ToolboxControl 中的项目

发布于 2024-09-28 06:55:52 字数 1147 浏览 4 评论 0原文

我正在创建一个重新托管工作流设计器的应用程序。我所做的是遵循 Apress 的 Pro WF 4 书籍中的教程。

本教程的原理是:
1.使用WorkflowDesigner类读取工作流xaml文件,并将WorkflowDesigner.ViewPropertyView属性绑定到ContentControl中用户界面。
2. 使用System.Activities.Presentation.Toolbox.ToolboxControl类创建类似VS的工具箱,以便用户可以拖放添加到该工具箱中的任何活动
3. ToolboxControl 使用 ToolboxCategoryToolboxItemWrapper 构建其内容。

好的,我的问题与 ToolboxItemWrapper 类相关。根据文档,构造函数使用的是类类型,而不是实例。所以当我们拖放时,它会将类实例化为实例。
这是文档:
http://msdn.microsoft.com/en -us/library/system.activities.presentation.toolbox.toolboxitemwrapper.aspx

但是,我想要破解 ToolboxItemWrapper 以便它可以接受一个实例,然后当我们拖放它时进入 WorkflowDesigner.View 中,视图将显示该实例。

关于如何实现此功能的任何想法或线索?

我需要此功能的原因:
我们希望让用户在将“实例”添加到设计器时更容易。当工具箱中有“类型”时,拖放后您需要设置参数。当工具箱中有“实例”时,用户所需要做的只是拖放即可。无需输入参数来设置“类型”。用户创建工作流程时的步骤更少。

另一个限制是工具箱中的活动列表取决于特定模块。该特定模块将生成实例列表。然后我想将这些生成的实例转换为工具箱中的条目。我会在问题中添加此信息

I'm creating an application that rehost workflow designer. What I did is following the tutorial from Apress' Pro WF 4 books.

The principle of the tutorial is:
1. Use WorkflowDesigner class to read workflow xaml file, and bind WorkflowDesigner.View and PropertyView property into ContentControl in the UI.
2. Use System.Activities.Presentation.Toolbox.ToolboxControl class to create VS-like Toolbox so that user can drag-and-drop whatever activities that added into this toolbox
3. ToolboxControl uses ToolboxCategory and ToolboxItemWrapper to construct its content.

Okay, my question is here related to ToolboxItemWrapper class. Based on the documentation, the constructor is using a Class Type, not an Instance. So when we drag and drop, it will instantiate the class into an instance.
Here is the documentation:
http://msdn.microsoft.com/en-us/library/system.activities.presentation.toolbox.toolboxitemwrapper.aspx

However, what I want to hack ToolboxItemWrapper so that it can accept an instance, then when we drag and drop it into WorkflowDesigner.View, the View will show the instance.

Any idea or clues how to achieve this functionality?

Reason why I need this feature:
We want to make it easier for user when adding an 'instance' into the designer. when you have a 'type' in toolbox, after dragging and dropping you need to setup the parameter. When we have 'instance' in toolbox, what user needs to do is just dragging and dropping and that's all. No need to enter parameter to set the 'type'. Less steps for user when creating their workflow.

Another constraint is the list of activities in the toolbox depends on a specific module. This specific module will generate a list of instances. Then I want to convert these generated instances into entries in toolbox. I'll add this info on the questions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等往事风中吹 2024-10-05 06:55:52

听起来您需要使用 IActivityTemplateFactory 接口。在这种情况下,当将活动拖到设计器上时,将调用 Create() 方法,并且您可以在返回的活动实例中设置属性等。这是将 ReceiveAndSendReply 活动对拖到设计图面上时所使用的内容。

It sounds like you need to use the IActivityTemplateFactory interface. In that case the Create() method is called when an activity is dragged onto the designer and you can set properties etc in the activity instance you return. This is what is used when you drag a ReceiveAndSendReply activity pair onto the design surface.

拥有 2024-10-05 06:55:52

经过一些调查后,Reflection 和 IActivityTemplate 可以帮助克服实例约束。

示例代码如下,感谢来自 MSDN 论坛的 Anders Liu

  • 编写一个名为 DynamicActivityTemplate 的类来实现 IActivityTemplateFactory。它的实现如下:

     公共抽象类 DynamicActivityTemplateFactory : IActivityTemplateFactory
         {
          公共虚拟字符串 GetActivity()
          {
           返回空值;
          }
    
          公共 System.Activities.Activity Create(System.Windows.DependencyObject 目标)
          {
           返回 XamlServices.Load(new StringReader(GetActivity())) 作为活动;
          }
         }

  • 当您获取生成的活动实例时,对于每个活动实例,您需要动态创建一个继承自 DynamicActivityTemplateFactory 的类型。每个类型都会重写方法 GetActivity() 并返回其实例的 xaml。以下是如何创建此类动态类型的示例:

    <前><代码>
    AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("GenerateActivities"), AssemblyBuilderAccess.RunAndSave);
    ModuleBuilder mb = ab.DefineDynamicModule("GenerateActivities", "GenerateActivities.dll");
    TypeBuilder tb = mb.DefineType("ActivityTemplateFactory4Sequence", TypeAttributes.Public | TypeAttributes.Class, typeof(DynamicActivityTemplateFactory));
    MethodBuilder methodb = tb.DefineMethod("GetActivity", MethodAttributes.Public | MethodAttributes.Virtual, typeof(string), null);
    ILGenerator msil = methodb.GetILGenerator();
    msil.Emit(OpCodes.Ldstr, XamlServices.Save(new Sequence() { DisplayName = "测试" }));
    msil.Emit(OpCodes.Ret);
    类型 t = tb.CreateType();
    ab.Save("GenerateActivities.dll");
    Assembly.Load(new AssemblyName("GenerateActivities"));

    toolbox.Categories[0].Add(new ToolboxItemWrapper(t));

  • 将这些动态生成的类型添加到工具箱。

    在这种情况下,您为每个实例创建工厂类型,然后在工具箱中使用这些工厂。这些工厂在交给设计师时会创建活动。我认为这适合您的情况,希望有所帮助。

  • 原帖来自MSDN论坛:
    http://social.msdn .microsoft.com/Forums/en-US/wfprerelease/thread/1b756014-72a0-483f-99ef-4f9e6e2e2324

    After doing some investigation, Reflection and IActivityTemplate can help to overcome the instance constraint.

    The sample code are below, credit to Anders Liu from MSDN Forum

  • Write a class called DynamicActivityTemplate that implement IActivityTemplateFactory. Its impelementation looks like:

        public abstract class DynamicActivityTemplateFactory : IActivityTemplateFactory
         {
          public virtual string GetActivity()
          {
           return null;
          }
    
          public System.Activities.Activity Create(System.Windows.DependencyObject target)
          {
           return XamlServices.Load(new StringReader(GetActivity())) as Activity;
          }
         }
  • When you get your generated activity instances, for each of them, you need dynamically create a Type that inherite from DynamicActivityTemplateFactory. Every type override the method GetActivity() and returns its instance's xaml. Following is a sample of how to create such dynamic type:

    
       AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("GeneratedActivities"), AssemblyBuilderAccess.RunAndSave);
       ModuleBuilder mb = ab.DefineDynamicModule("GeneratedActivities", "GeneratedActivities.dll");
       TypeBuilder tb = mb.DefineType("ActivityTemplateFactory4Sequence", TypeAttributes.Public | TypeAttributes.Class, typeof(DynamicActivityTemplateFactory));
       MethodBuilder methodb = tb.DefineMethod("GetActivity", MethodAttributes.Public | MethodAttributes.Virtual, typeof(string), null);
       ILGenerator msil = methodb.GetILGenerator();
       msil.Emit(OpCodes.Ldstr, XamlServices.Save(new Sequence() { DisplayName = "Test" }));
       msil.Emit(OpCodes.Ret);
       Type t = tb.CreateType();
       ab.Save("GeneratedActivities.dll");
       Assembly.Load(new AssemblyName("GeneratedActivities"));

    toolbox.Categories[0].Add(new ToolboxItemWrapper(t));

  • Add those dynamic generated types to toolbox.

    In this case, you create factory types for each of those instances, and then use these factories in toolbox. These factorys will create activities when they are droped to designer. I think this would work for your case, hope it helps.

  • Original post from MSDN forum:
    http://social.msdn.microsoft.com/Forums/en-US/wfprerelease/thread/1b756014-72a0-483f-99ef-4f9e6e2e2324

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文