Como: criar um designer personalizado de atividades
Designers personalizados de atividade são normalmente implementados de modo que as atividades passível de composição sejam associados com outras atividades cujos os designers podem ser ignorados sobre a superfície de design com eles. Essa funcionalidade requer que um designer personalizado de atividade fornece uma “zona para arrastar e soltar” onde uma atividade arbitrária pode ser colocada e também significa gerenciar a coleção resultante dos elementos na superfície de design. Este tópico descreve como criar um designer personalizado de atividade que contém uma área para arrastar e soltar e como criar um designer personalizado de atividade que fornece a funcionalidade de edição necessária gerenciar a coleção de elementos de designer.
Designers personalizados de atividade normalmente herdam de ActivityDesigner que é tem como padrão o tipo base do designer de atividade para todas as atividades sem um designer específico. Este tipo fornece a experiência em tempo de design de interagir com a grade de propriedade e configurar aspectos básicos como gerenciar cores e ícones.
ActivityDesigner usa dois controles auxiliar, WorkflowItemPresenter e WorkflowItemsPresenter para tornar mais fácil desenvolver designer personalizadas de atividade. Manipular a funcionalidade comum como arrastar e soltar de elementos filho, de exclusão, de seleção, e a adição desses elementos filho. O WorkflowItemPresenter permite que um único elemento de interface do usuário filho dentro, fornecendo a “zona para arrastar e soltar”, enquanto WorkflowItemsPresenter pode fornecer suporte vários elementos de interface do usuário, incluindo a funcionalidade adicional como ordenar, excluir, mover, e adicione de elementos filhos.
A outra parte fundamental de artigo que precisa de realce na implementação de um designer personalizado de atividade refere-se à maneira como que as edições visuais são associadas usando os dados de WPF que se associam à instância armazenado na memória que nós estamos edição no designer. Isso é feito pela árvore modelo de item, que também é responsável para ativar a notificação de alteração e o rastreamento de eventos como alterações nos estados.
Este tópico descreve dois procedimentos.
O primeiro procedimento descreve como criar um designer personalizado de atividade com WorkflowItemPresenter que fornece a área para arrastar e soltar que recebe outras atividades. Este procedimento baseia-se na amostra de Designers Compostos Personalizados - Apresentador de Item do Item de Fluxo de Trabalho.
O segundo procedimento descreve como criar um designer personalizado de atividade com WorkflowItemsPresenter que fornece funcionalidade necessária edição de uma coleção de elementos contidos. Este procedimento baseia-se na amostra de Designers Compostos Personalizados - Apresentador de Itens do Item de Fluxo de Trabalho.
Para criar um designer personalizado de atividade com uma área para arrastar e soltar usando WorkflowItemPresenter
Inicie o Visual Studio 2010.
No menu Arquivo , aponte para Novoe selecione Projeto.
A caixa de diálogo Novo Projeto será aberta.
No painel de Modelos Instalados, selecione Janelas da categoria do seu idioma preferencial.
No painel de Modelos, selecione Aplicativo do WPF.
Na caixa Nome, insira
UsingWorkflowItemPresenter
.Na caixa de Local, digite o diretório em que você deseja salvar seu projeto, clique em Procurar para navegar até ela.
Na caixa de 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 do Microsoft Visual Studio.
Clique com o botão direito do mouse no projeto UsingWorkflowItemPresenter em Gerenciador de Soluções, selecione Adicionar, em seguida Novo Item... para trazer a caixa de diálogo Adicionar novo item e selecione a categoria de WPF da seção de Modelos Instalados à esquerda.
Selecione o modelo da Janela (WPF), nomeie-o
RehostingWFDesigner
e clique em Adicionar.Abra o arquivo RehostingWFDesigner.xaml e cole o seguinte código nele para definir uma interface de usuário para o 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 com um tipo de atividade, você deve registrar que o designer de atividade com o armazenamento de metadados. Para fazer isso, adicione o método de
RegisterMetadata
a classe deRehostingWFDesigner
. No escopo do método deRegisterMetadata
, crie um objeto de AttributeTableBuilder e chame o método de AddCustomAttributes para adicionar os atributos nele. Chame o método de AddAttributeTable para adicionar AttributeTable para o armazenamento de metadados. O código a seguir contém a lógica rehosting para o designer. Registra os metadados, colocaSimpleNativeActivity
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 de 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 OK.
Usando o mesmo procedimento, adicione referências para os seguintes conjuntos:
System.Data.DataSetExtensions.dll
System.Activities.Presentation.dll
System.ServiceModel.Activities.dll
Abra o arquivo App.xaml e altere o valor de StartUpUri para “RehostingWFDesigner.xaml”.
Clique com o botão direito do mouse no projeto UsingWorkflowItemPresenter em Gerenciador de Soluções, selecione Adicionar, em seguida em Novo Item... para abrir a caixa de diálogo Adicionar novo item e selecione a categoria de Fluxo de Trabalho na seção Modelos Instalados à esquerda.
Selecione o modelo Designer de atividade, nomeie-o
SimpleNativeDesigner
e clique em Adicionar.Abra o arquivo SimpleNativeDesigner.xaml e cole o seguinte código nele. Observe ActivityDesigner usa esse código como seu elemento raiz e mostra como associar é usado para integrar WorkflowItemPresenter no designer para que um tipo filho pode ser exibido no designer composto de atividade.
Observação
O esquema para ActivityDesigner permite a adição de apenas um elemento filho a sua definição personalizado de designer de atividade; no entanto, esse elemento pode ser
StackPanel
,Grid
, ou outro elemento composto de 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 em Gerenciador de Soluções, selecione Adicionar, em seguida em Novo Item... para abrir a caixa de diálogo Adicionar novo item e selecione a categoria de Fluxo de Trabalho na seção Modelos Instalados à esquerda.
Selecione o modelo Atividade do código, nomeie-o
SimpleNativeActivity
e clique em Adicionar.Implementar a classe de
SimpleNativeActivity
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 Solução de compilação no menu Compilação.
Selecione Iniciar sem depuração no menu Depuração para abrir a janela de design personalizado hospedado novamente.
Para criar um designer personalizado de atividade que usa WorkflowItemsPresenter
O procedimento para o segundo designer personalizado de atividade é a paralelas o primeiro com algumas alterações, o primeiro de que é nomear o segundo aplicativo
UsingWorkflowItemsPresenter
. Também este aplicativo não define uma nova atividade personalizado.As principais diferenças estão contidas nos arquivos CustomParallelDesigner.xaml e RehostingWFDesigner.xaml.cs. Aqui está o código do arquivo CustomParallelDesigne.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 nova hospedagem:
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()); } } }