Поделиться через


Как создать настраиваемый конструктор действий

Пользовательские конструкторы действий обычно реализуются таким образом, что их связанные действия сочетаются с другими действиями, конструкторы которых могут сбрасываться вместе с ними в область конструктора. Для этого требуется, чтобы настраиваемый конструктор действий предоставлял "зону удаления", в которой можно поместить произвольное действие, а также средства для управления результирующей коллекцией элементов в области конструктора. В этом разделе описано создание пользовательского конструктора действий, содержащего «зону перетаскивания», а также создание пользовательского конструктора действий, предоставляющего функции редактирования, необходимые для управления коллекцией элементов конструктора.

Пользовательские конструкторы действий обычно наследуют от ActivityDesigner, который является базовым типом конструктора действий по умолчанию для любых действий без определенного конструктора. Этот тип обеспечивает взаимодействие с таблицей свойств во время разработки и настройку основных аспектов, например, управления цветами и значками.

Для упрощения разработки пользовательских конструкторов действий в конструкторе ActivityDesigner используют два элемента управления помощника, WorkflowItemPresenter и WorkflowItemsPresenter. Они обрабатывают общие функции, например перетаскивание дочерних элементов, удаление, выделение и добавление этих дочерних элементов. Он WorkflowItemPresenter позволяет одному дочернему элементу пользовательского интерфейса внутри, предоставляя "зону удаления", в то время WorkflowItemsPresenter как она может обеспечить поддержку нескольких элементов пользовательского интерфейса, включая дополнительные функции, такие как упорядочение, перемещение, удаление и добавление дочерних элементов.

Другая ключевая часть истории, требующая выделения в реализации пользовательского конструктора действий, касается того, как визуальные изменения привязаны с помощью привязки данных WPF к экземпляру, хранящемуся в памяти о том, что мы редактируем в конструкторе. Это достигается с помощью дерева элементов модели, которое также обеспечивает уведомления об изменениях и отслеживание таких событий, как изменения состояний.

В данном подразделе описаны две процедуры.

  1. Первая процедура описывает создание пользовательских конструкторов действий с WorkflowItemPresenter, предоставляющим «зону перетаскивания», в которую можно помещать другие действия. Эта процедура основана на примере пользовательского составного конструктора — образца докладчика элементов рабочего процесса.

  2. Вторая процедура описывает создание пользовательских конструкторов действий с элементом управления помощника WorkflowItemsPresenter, предоставляющим функции, необходимые для изменения коллекции содержащихся в нем элементов. Эта процедура основана на примере пользовательского составного конструктора — образца докладчика элементов рабочего процесса.

Создание пользовательского конструктора действий с "зоной сброса" с использованием WorkflowItemPresenter

  1. Запустите Visual Studio 2010.

  2. В меню Файл последовательно выберите команды Создатьи Проект.

    Откроется диалоговое окно Создание проекта .

  3. В области установленных шаблонов выберите Windows из предпочитаемой языковой категории.

  4. В области шаблонов выберите приложение WPF.

  5. В поле Имя введите UsingWorkflowItemPresenter.

  6. В поле "Расположение" введите каталог, в котором вы хотите сохранить проект, или нажмите кнопку "Обзор", чтобы перейти к нему.

  7. В поле решения примите значение по умолчанию.

  8. Щелкните OK.

  9. Щелкните правой кнопкой мыши файл MainWindows.xaml в Обозреватель решений, выберите "Удалить" и подтвердите его в диалоговом окне Microsoft Visual Studio.

  10. Щелкните правой кнопкой мыши проект UsingWorkflowItemPresenter в Обозреватель решений, выберите "Добавить", а затем "Создать элемент", чтобы открыть диалоговое окно "Добавить новый элемент" и выберите категорию WPF в разделе "Установленные шаблоны" слева.

  11. Выберите шаблон окна (WPF), назовите его RehostingWFDesignerи нажмите кнопку "Добавить".

  12. Откройте файл RehostingWFDesigner.xaml и вставьте в него следующий код, чтобы определить пользовательский интерфейс приложения:

    <Window x:Class=" UsingWorkflowItemPresenter.RehostingWFDesigner"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:sapt="clr-namespace:System.Activities.Presentation.Toolbox;assembly=System.Activities.Presentation"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            Title="Window1" Height="600" Width="900">
        <Window.Resources>
            <sys:String x:Key="AssemblyName">System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</sys:String>
        </Window.Resources>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2*"/>
                <ColumnDefinition Width="7*"/>
                <ColumnDefinition Width="3*"/>
            </Grid.ColumnDefinitions>
            <Border Grid.Column="0">
                <sapt:ToolboxControl Name="Toolbox">
                    <sapt:ToolboxCategory CategoryName="Basic">
                        <sapt:ToolboxItemWrapper AssemblyName="{StaticResource AssemblyName}" >
                            <sapt:ToolboxItemWrapper.ToolName>
                                System.Activities.Statements.Sequence
                            </sapt:ToolboxItemWrapper.ToolName>
                           </sapt:ToolboxItemWrapper>
                        <sapt:ToolboxItemWrapper  AssemblyName="{StaticResource AssemblyName}">
                            <sapt:ToolboxItemWrapper.ToolName>
                                System.Activities.Statements.WriteLine
                            </sapt:ToolboxItemWrapper.ToolName>
    
                        </sapt:ToolboxItemWrapper>
                        <sapt:ToolboxItemWrapper  AssemblyName="{StaticResource AssemblyName}">
                            <sapt:ToolboxItemWrapper.ToolName>
                                System.Activities.Statements.If
                            </sapt:ToolboxItemWrapper.ToolName>
    
                        </sapt:ToolboxItemWrapper>
                        <sapt:ToolboxItemWrapper  AssemblyName="{StaticResource AssemblyName}">
                            <sapt:ToolboxItemWrapper.ToolName>
                                System.Activities.Statements.While
                            </sapt:ToolboxItemWrapper.ToolName>
    
                        </sapt:ToolboxItemWrapper>
                    </sapt:ToolboxCategory>
                </sapt:ToolboxControl>
            </Border>
            <Border Grid.Column="1" Name="DesignerBorder"/>
            <Border Grid.Column="2" Name="PropertyBorder"/>
        </Grid>
    </Window>
    
  13. Чтобы связать конструктор действия с типом действия, необходимо зарегистрировать конструктор действия в хранилище метаданных. Для этого добавьте метод RegisterMetadata в класс RehostingWFDesigner. В область RegisterMetadata метода создайте AttributeTableBuilder объект и вызовите AddCustomAttributes метод, чтобы добавить в него атрибуты. Вызовите метод AddAttributeTable, чтобы добавить AttributeTable в хранилище метаданных. Следующий код содержит логику повторного размещения для конструктора. Он регистрирует метаданные, помещает действие SimpleNativeActivity в область элементов и создает рабочий процесс. Вставьте этот код в файл RehostingWFDesigner.xaml.cs .

    using System;
    using System.Activities.Core.Presentation;
    using System.Activities.Presentation;
    using System.Activities.Presentation.Metadata;
    using System.Activities.Presentation.Toolbox;
    using System.Activities.Statements;
    using System.ComponentModel;
    using System.Windows;
    
    namespace UsingWorkflowItemPresenter
    {
        // Interaction logic for RehostingWFDesigner.xaml
        public partial class RehostingWFDesigner
        {
            public RehostingWFDesigner()
            {
                InitializeComponent();
            }
    
            protected override void OnInitialized(EventArgs e)
            {
                base.OnInitialized(e);
                // Register metadata.
                (new DesignerMetadata()).Register();
                RegisterCustomMetadata();
                // Add custom activity to toolbox.
                Toolbox.Categories.Add(new ToolboxCategory("Custom activities"));
                Toolbox.Categories[1].Add(new ToolboxItemWrapper(typeof(SimpleNativeActivity)));
    
                // Create the workflow designer.
                var wd = new WorkflowDesigner();
                wd.Load(new Sequence());
                DesignerBorder.Child = wd.View;
                PropertyBorder.Child = wd.PropertyInspectorView;
    
            }
    
            void RegisterCustomMetadata()
            {
                var builder = new AttributeTableBuilder();
                builder.AddCustomAttributes(typeof(SimpleNativeActivity), new DesignerAttribute(typeof(SimpleNativeDesigner)));
                MetadataStore.AddAttributeTable(builder.CreateTable());
            }
        }
    }
    
  14. Щелкните правой кнопкой мыши каталог "Ссылки" в Обозреватель решений и выберите "Добавить ссылку...", чтобы открыть диалоговое окно "Добавить ссылку".

  15. Щелкните вкладку .NET , найдите сборку с именем System.Activities.Core.Presentation, выберите ее и нажмите кнопку "ОК".

  16. Таким же образом добавьте ссылки на следующие сборки:

    1. System.Data.DataSetExtensions.dll

    2. System.Activities.Presentation.dll

    3. System.ServiceModel.Activities.dll

  17. Откройте файл App.xaml и измените значение StartUpUri на RehostingWFDesigner.xaml.

  18. Щелкните правой кнопкой мыши проект UsingWorkflowItemPresenter в Обозреватель решений, выберите "Добавить", а затем "Создать элемент", чтобы открыть диалоговое окно "Добавить новый элемент" и выберите категорию рабочего процесса в разделе "Установленные шаблоны" слева.

  19. Выберите шаблон конструктора действий, назовите его SimpleNativeDesignerи нажмите кнопку "Добавить".

  20. Откройте файл SimpleNativeDesigner.xaml и вставьте в него следующий код. Обратите внимание, что этот код использует ActivityDesigner в качестве корневого элемента и показывает, как привязка используется для интеграции WorkflowItemPresenter в конструктор, чтобы дочерний тип можно было отобразить в конструкторе составных действий.

    Примечание.

    Схема для ActivityDesigner позволяет добавлять только один дочерний элемент в определение пользовательского конструктора действий. Однако этим элементом может быть StackPanel, Grid или другой составной элемент пользовательского интерфейса.

    <sap:ActivityDesigner x:Class=" UsingWorkflowItemPresenter.SimpleNativeDesigner"
        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:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation">
        <sap:ActivityDesigner.Resources>
            <DataTemplate x:Key="Collapsed">
                <StackPanel>
                    <TextBlock>This is the collapsed view</TextBlock>
                </StackPanel>
            </DataTemplate>
            <DataTemplate x:Key="Expanded">
                <StackPanel>
                    <TextBlock>Custom Text</TextBlock>
                    <sap:WorkflowItemPresenter Item="{Binding Path=ModelItem.Body, Mode=TwoWay}"
                                            HintText="Please drop an activity here" />
                </StackPanel>
            </DataTemplate>
            <Style x:Key="ExpandOrCollapsedStyle" TargetType="{x:Type ContentPresenter}">
                <Setter Property="ContentTemplate" Value="{DynamicResource Collapsed}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=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>
    
  21. Щелкните правой кнопкой мыши проект UsingWorkflowItemPresenter в Обозреватель решений, выберите "Добавить", а затем "Создать элемент", чтобы открыть диалоговое окно "Добавить новый элемент" и выберите категорию рабочего процесса в разделе "Установленные шаблоны" слева.

  22. Выберите шаблон действия кода, назовите его SimpleNativeActivityи нажмите кнопку "Добавить".

  23. SimpleNativeActivity Реализуйте класс, введя следующий код в файл SimpleNativeActivity.cs:

    using System.Activities;
    
    namespace UsingWorkflowItemPresenter
    {
        public sealed class SimpleNativeActivity : NativeActivity
        {
            // this property contains an activity that will be scheduled in the execute method
            // the WorkflowItemPresenter in the designer is bound to this to enable editing
            // of the value
            public Activity Body { get; set; }
    
            protected override void CacheMetadata(NativeActivityMetadata metadata)
            {
               metadata.AddChild(Body);
               base.CacheMetadata(metadata);
    
            }
    
            protected override void Execute(NativeActivityContext context)
            {
                context.ScheduleActivity(Body);
            }
        }
    }
    
  24. Выберите "Создать решение" в меню "Сборка".

  25. Выберите "Пуск без отладки" в меню отладки , чтобы открыть повторно размещенное пользовательское окно конструктора.

Создание пользовательского конструктора действий с использованием WorkflowItemsPresenter

  1. Процедура второго пользовательского конструктора действий — это параллелизм первого с несколькими изменениями, первое из которых — имя второго приложения UsingWorkflowItemsPresenter. Кроме того, это приложение не определяет новое пользовательское действие.

  2. Основные различия содержатся в файлах CustomParallelDesigner.xaml и RehostingWFDesigner.xaml.cs . Ниже приведен код из файла CustomParallelDesigner.xaml , который определяет пользовательский интерфейс:

    <sap:ActivityDesigner x:Class=" UsingWorkflowItemsPresenter.CustomParallelDesigner"
        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:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation">
        <sap:ActivityDesigner.Resources>
            <DataTemplate x:Key="Collapsed">
                <TextBlock>This is the Collapsed View</TextBlock>
            </DataTemplate>
            <DataTemplate x:Key="Expanded">
                <StackPanel>
                    <TextBlock HorizontalAlignment="Center">This is the</TextBlock>
                    <TextBlock HorizontalAlignment="Center">extended view</TextBlock>
                    <sap:WorkflowItemsPresenter HintText="Drop Activities Here"
                                        Items="{Binding Path=ModelItem.Branches}">
                        <sap:WorkflowItemsPresenter.SpacerTemplate>
                            <DataTemplate>
                                <Ellipse Width="10" Height="10" Fill="Black"/>
                            </DataTemplate>
                        </sap:WorkflowItemsPresenter.SpacerTemplate>
                        <sap:WorkflowItemsPresenter.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal"/>
                            </ItemsPanelTemplate>
                        </sap:WorkflowItemsPresenter.ItemsPanel>
                    </sap:WorkflowItemsPresenter>
                </StackPanel>
            </DataTemplate>
            <Style x:Key="ExpandOrCollapsedStyle" TargetType="{x:Type ContentPresenter}">
                <Setter Property="ContentTemplate" Value="{DynamicResource Collapsed}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=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>
    
  3. Ниже приведен код из файла RehostingWFDesigner.xaml.cs , который предоставляет логику повторного размещения:

    using System;
    using System.Activities.Core.Presentation;
    using System.Activities.Presentation;
    using System.Activities.Presentation.Metadata;
    using System.Activities.Statements;
    using System.ComponentModel;
    using System.Windows;
    
    namespaceUsingWorkflowItemsPresenter
    {
        public partial class RehostingWfDesigner : Window
        {
            public RehostingWfDesigner()
            {
                InitializeComponent();
            }
    
            protected override void OnInitialized(EventArgs e)
            {
                base.OnInitialized(e);
                // Register metadata.
                (new DesignerMetadata()).Register();
                RegisterCustomMetadata();
    
                // Create the workflow designer.
                var wd = new WorkflowDesigner();
                wd.Load(new Sequence());
                DesignerBorder.Child = wd.View;
                PropertyBorder.Child = wd.PropertyInspectorView;
    
            }
    
            void RegisterCustomMetadata()
            {
                var builder = new AttributeTableBuilder();
                builder.AddCustomAttributes(typeof(Parallel), new DesignerAttribute(typeof(CustomParallelDesigner)));
                MetadataStore.AddAttributeTable(builder.CreateTable());
            }
        }
    }
    

См. также