Como: Criar um designer de atividade personalizado
Os designers de atividades personalizadas são normalmente implementados para que suas atividades associadas sejam combináveis com outras atividades cujos designers podem ser deixados na superfície de design com eles. Essa funcionalidade requer que um designer de atividade personalizado forneça uma "zona de queda" onde uma atividade arbitrária pode ser colocada e também os meios para gerenciar a coleção resultante de elementos na superfície de design. Este tópico descreve como criar um designer de atividade personalizado que contém essa zona de soltar e como criar um designer de atividade personalizado que fornece a funcionalidade de edição necessária para gerenciar a coleção de elementos de designer.
Os designers de atividades personalizadas normalmente herdam do qual é o tipo de designer de ActivityDesigner atividade base padrão para quaisquer atividades sem um designer específico. Esse tipo fornece a experiência em tempo de design de interagir com a grade de propriedades e configurar aspetos básicos, como o gerenciamento de cores e ícones.
ActivityDesigner usa dois controles auxiliares WorkflowItemPresenter e WorkflowItemsPresenter facilita o desenvolvimento de designers de atividades personalizados. Eles lidam com funcionalidades comuns, como arrastar e soltar elementos filho, exclusão, seleção e adição desses elementos filho. O WorkflowItemPresenter permite que um único elemento filho da interface do usuário dentro, fornecendo a "zona de soltar", enquanto o WorkflowItemsPresenter pode fornecer suporte a vários elementos da interface do usuário, incluindo funcionalidades adicionais, como ordenar, mover, excluir e adicionar elementos filho.
A outra parte importante da história que precisa ser destacada na implementação de um designer de atividade personalizado diz respeito à maneira como as edições visuais são vinculadas usando a vinculação de dados WPF à instância armazenada na memória do que estamos editando no designer. Isso é feito pela árvore Item de modelo, que também é responsável por habilitar a notificação de alterações e o rastreamento de eventos, como alterações em estados.
Este tópico descreve dois procedimentos.
O primeiro procedimento descreve como criar um designer de atividade personalizado com um WorkflowItemPresenter que fornece a zona de descarte que recebe outras atividades. Este procedimento é baseado no exemplo Custom Composite Designers - Workflow Item Presenter .
O segundo procedimento descreve como criar um designer de atividade personalizado com um WorkflowItemsPresenter que fornece a funcionalidade necessária para editar uma coleção de elementos contidos. Este procedimento é baseado no exemplo Custom Composite Designers - Workflow Items Presenter .
Para criar um designer de atividade personalizado com uma zona de descarte usando WorkflowItemPresenter
Inicie o Visual Studio 2010.
No menu Arquivo, aponte para Novo e selecione Projeto....
A caixa de diálogo Novo projeto é aberta.
No painel Modelos Instalados, selecione Windows na categoria de idioma de sua preferência.
No painel Modelos, selecione Aplicativo WPF.
Na caixa Nome, digite
UsingWorkflowItemPresenter
.Na caixa Local, insira o diretório no qual deseja salvar seu projeto ou clique em Procurar para navegar até ele.
Na caixa Solução, aceite o valor padrão.
Clique em OK.
Clique com o botão direito do mouse no arquivo MainWindows.xaml no Gerenciador de Soluções, selecione Excluir e confirme OK na caixa de diálogo Microsoft Visual Studio.
Clique com o botão direito do mouse no projeto UsingWorkflowItemPresenter no Gerenciador de Soluções, selecione Adicionar e, em seguida , Novo Item... para abrir a caixa de diálogo Adicionar Novo Item e selecione a categoria WPF na seção Modelos Instalados à esquerda.
Selecione o modelo Janela (WPF), nomeie-o
RehostingWFDesigner
e clique em Adicionar.Abra o arquivo RehostingWFDesigner.xaml e cole o seguinte código nele para definir a interface do usuário do aplicativo:
<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>
Para associar um designer de atividade a um tipo de atividade, você deve registrar esse designer de atividade no repositório de metadados. Para fazer isso, adicione o
RegisterMetadata
método àRehostingWFDesigner
classe. Dentro do escopo doRegisterMetadata
método, crie um AttributeTableBuilder objeto e chame o AddCustomAttributes método para adicionar os atributos a ele. Chame o AddAttributeTable método para adicionar o AttributeTable ao repositório de metadados. O código a seguir contém a lógica de rehospedagem para o designer. Ele registra os metadados, coloca osSimpleNativeActivity
na caixa de ferramentas e cria o fluxo de trabalho. Coloque esse código no arquivo 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()); } } }
Clique com o botão direito do mouse no diretório Referências no Gerenciador de Soluções e selecione Adicionar Referência ... para abrir a caixa de diálogo Adicionar Referência .
Clique na guia .NET, localize o assembly chamado System.Activities.Core.Presentation, selecione-o e clique em OK.
Usando o mesmo procedimento, adicione referências aos seguintes assemblies:
System.Data.DataSetExtensions.dll
System.Activities.Presentation.dll
System.ServiceModel.Activities.dll
Abra o arquivo App.xaml e altere o valor do StartUpUri para "RehostingWFDesigner.xaml".
Clique com o botão direito do mouse no projeto UsingWorkflowItemPresenter no Gerenciador de Soluções, selecione Adicionar e, em seguida , Novo Item... para abrir a caixa de diálogo Adicionar Novo Item e selecione a categoria Fluxo de Trabalho na seção Modelos Instalados à esquerda.
Selecione o modelo do Designer de Atividade , nomeie-o
SimpleNativeDesigner
e clique em Adicionar.Abra o arquivo SimpleNativeDesigner.xaml e cole o código a seguir nele. Observe que esse código usa ActivityDesigner como seu elemento raiz e mostra como a vinculação é usada para integrar WorkflowItemPresenter ao seu designer para que um tipo filho possa ser exibido em seu designer de atividade composta.
Nota
O esquema para ActivityDesigner permite a adição de apenas um elemento filho à sua definição de designer de atividade personalizada, no entanto, esse elemento pode ser um
StackPanel
,Grid
ou algum outro elemento composto da interface do usuário.<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>
Clique com o botão direito do mouse no projeto UsingWorkflowItemPresenter no Gerenciador de Soluções, selecione Adicionar e, em seguida , Novo Item... para abrir a caixa de diálogo Adicionar Novo Item e selecione a categoria Fluxo de Trabalho na seção Modelos Instalados à esquerda.
Selecione o modelo Atividade de código, nomeie-o
SimpleNativeActivity
e clique em Adicionar.Implemente a
SimpleNativeActivity
classe inserindo o seguinte código no arquivo 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); } } }
Selecione Build Solution no menu Build .
Selecione Iniciar sem depuração no menu Depurar para abrir a janela de design personalizado rehospedada.
Para criar um designer de atividades personalizado usando WorkflowItemsPresenter
O procedimento para o segundo designer de atividade personalizada é o paralelo do primeiro com algumas modificações, a primeira das quais é nomear o segundo aplicativo
UsingWorkflowItemsPresenter
. Além disso, este aplicativo não define uma nova atividade personalizada.As principais diferenças estão contidas nos arquivos CustomParallelDesigner.xaml e RehostingWFDesigner.xaml.cs . Aqui está o código do arquivo CustomParallelDesigner.xaml que define a interface do usuário:
<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>
Aqui está o código do arquivo RehostingWFDesigner.xaml.cs que fornece a lógica de rehospedagem:
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()); } } }