Instrukcje: Tworzenie niestandardowego projektanta działań
Projektanci działań niestandardowych są zwykle implementowani tak, aby ich skojarzone działania były komponowane z innymi działaniami, których projektanci mogą zostać porzuceni do powierzchni projektowej z nimi. Ta funkcja wymaga, aby niestandardowy projektant działań zapewniał "strefę upuszczania", w której można umieścić dowolne działanie, a także środki do zarządzania wynikową kolekcją elementów na powierzchni projektowej. W tym temacie opisano sposób tworzenia niestandardowego projektanta działań zawierającego taką strefę upuszczania oraz jak utworzyć niestandardowego projektanta działań, który zapewnia możliwość edytowania funkcji potrzebnych do zarządzania kolekcją elementów projektanta.
Projektanci działań niestandardowych zwykle dziedziczą, z ActivityDesigner którego jest domyślnym podstawowym typem projektanta działań dla jakichkolwiek działań bez określonego projektanta. Ten typ zapewnia środowisko czasu projektowania interakcji z siatką właściwości i konfigurowanie podstawowych aspektów, takich jak zarządzanie kolorami i ikonami.
ActivityDesigner używa dwóch kontrolek WorkflowItemPresenter pomocnika i WorkflowItemsPresenter ułatwia tworzenie niestandardowych projektantów działań. Obsługują one typowe funkcje, takie jak przeciąganie i upuszczanie elementów podrzędnych, usuwanie, zaznaczanie i dodawanie tych elementów podrzędnych. Element WorkflowItemPresenter umożliwia korzystanie z pojedynczego podrzędnego elementu interfejsu użytkownika wewnątrz, udostępniając "strefę upuszczania", a jednocześnie WorkflowItemsPresenter może zapewnić obsługę wielu elementów interfejsu użytkownika, w tym dodatkowe funkcje, takie jak porządkowanie, przenoszenie, usuwanie i dodawanie elementów podrzędnych.
Druga kluczowa część artykułu, która wymaga wyróżnienia w implementacji niestandardowego projektanta działań, dotyczy sposobu, w jaki zmiany wizualne są powiązane przy użyciu powiązania danych WPF z wystąpieniem przechowywanym w pamięci tego, co edytujemy w projektancie. Jest to realizowane przez drzewo elementów modelu, które jest również odpowiedzialne za włączenie powiadomienia o zmianie i śledzenie zdarzeń, takich jak zmiany w stanach.
W tym temacie opisano dwie procedury.
Pierwsza procedura opisuje sposób tworzenia niestandardowego projektanta działań za pomocą elementu WorkflowItemPresenter , który udostępnia strefę upuszczania, która odbiera inne działania. Ta procedura jest oparta na przykładzie niestandardowych Projektant złożonych — prezentera elementu przepływu pracy.
Druga procedura opisuje sposób tworzenia niestandardowego projektanta działań za pomocą elementu WorkflowItemsPresenter , który zapewnia funkcjonalność wymaganą do edycji kolekcji zawartych elementów. Ta procedura jest oparta na przykładzie niestandardowych Projektant złożonych — prezenter elementów przepływu pracy.
Aby utworzyć niestandardowego projektanta działań ze strefą upuszczania przy użyciu elementu WorkflowItemPresenter
Uruchom program Visual Studio 2010.
W menu Plik wskaż pozycję Nowy, a następnie wybierz pozycję Projekt....
Zostanie otwarte okno dialogowe Nowy projekt .
W okienku Zainstalowane szablony wybierz pozycję Windows z preferowanej kategorii językowej.
W okienku Szablony wybierz pozycję Aplikacja WPF.
W polu Nazwa wprowadź .
UsingWorkflowItemPresenter
W polu Lokalizacja wprowadź katalog, w którym chcesz zapisać projekt, lub kliknij przycisk Przeglądaj, aby przejść do niego.
W polu Rozwiązanie zaakceptuj wartość domyślną.
Kliknij przycisk OK.
Kliknij prawym przyciskiem myszy plik MainWindows.xaml w Eksplorator rozwiązań, wybierz polecenie Usuń i potwierdź przycisk OK w oknie dialogowym Microsoft Visual Studio.
Kliknij prawym przyciskiem myszy projekt UsingWorkflowItemPresenter w Eksplorator rozwiązań, wybierz pozycję Dodaj, a następnie pozycję Nowy element... , aby wyświetlić okno dialogowe Dodawanie nowego elementu i wybrać kategorię WPF w sekcji Zainstalowane szablony po lewej stronie.
Wybierz szablon Okno (WPF), nadaj mu
RehostingWFDesigner
nazwę , a następnie kliknij przycisk Dodaj.Otwórz plik RehostingWF Projektant.xaml i wklej do niego następujący kod, aby zdefiniować interfejs użytkownika aplikacji:
<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>
Aby skojarzyć projektanta działań z typem działania, musisz zarejestrować tego projektanta działań w magazynie metadanych. W tym celu dodaj metodę
RegisterMetadata
RehostingWFDesigner
do klasy . W zakresieRegisterMetadata
metody utwórz obiekt i wywołaj AddCustomAttributes metodę AttributeTableBuilder , aby dodać do niej atrybuty. Wywołaj metodę , AddAttributeTable aby dodać AttributeTable element do magazynu metadanych. Poniższy kod zawiera logikę ponownego hostowania dla projektanta. Rejestruje metadane, umieszczaSimpleNativeActivity
je w przyborniku i tworzy przepływ pracy. Umieść ten kod w pliku RehostingWF Projektant.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()); } } }
Kliknij prawym przyciskiem myszy katalog References w Eksplorator rozwiązań i wybierz polecenie Dodaj odwołanie ... aby wyświetlić okno dialogowe Dodawanie odwołania.
Kliknij kartę .NET, znajdź zestaw o nazwie System.Activities.Core.Presentation, wybierz go i kliknij przycisk OK.
Korzystając z tej samej procedury, dodaj odwołania do następujących zestawów:
System.Data.DataSetExtensions.dll
System.Activities.Presentation.dll
System.ServiceModel.Activities.dll
Otwórz plik App.xaml i zmień wartość identyfikatora StartUpUri na "RehostingWF Projektant.xaml".
Kliknij prawym przyciskiem myszy projekt UsingWorkflowItemPresenter w Eksplorator rozwiązań, wybierz pozycję Dodaj, a następnie pozycję Nowy element..., aby wyświetlić okno dialogowe Dodawanie nowego elementu i wybierz kategorię Przepływ pracy w sekcji Zainstalowane szablony po lewej stronie.
Wybierz szablon Działanie Projektant, nadaj mu
SimpleNativeDesigner
nazwę , a następnie kliknij przycisk Dodaj.Otwórz plik SimpleNative Projektant.xaml i wklej do niego następujący kod. Należy pamiętać, że ten kod używa ActivityDesigner jako elementu głównego i pokazuje, jak powiązanie jest używane do integracji WorkflowItemPresenter z projektantem, aby w projektancie działań złożonych można było wyświetlić typ podrzędny.
Uwaga
Schemat umożliwia ActivityDesigner dodanie tylko jednego elementu podrzędnego do niestandardowej definicji projektanta działań. Jednak ten element może być elementem
StackPanel
,Grid
lub innym złożonym elementem interfejsu użytkownika.<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>
Kliknij prawym przyciskiem myszy projekt UsingWorkflowItemPresenter w Eksplorator rozwiązań, wybierz pozycję Dodaj, a następnie pozycję Nowy element..., aby wyświetlić okno dialogowe Dodawanie nowego elementu i wybierz kategorię Przepływ pracy w sekcji Zainstalowane szablony po lewej stronie.
Wybierz szablon Działanie kodu, nadaj mu
SimpleNativeActivity
nazwę , a następnie kliknij przycisk Dodaj.Zaimplementuj klasę
SimpleNativeActivity
, wprowadzając następujący kod do pliku 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); } } }
Wybierz pozycję Kompiluj rozwiązanie z menu Kompilacja.
Wybierz pozycję Start Without Debug (Rozpocznij bez debugowania) z menu Debug (Debugowanie), aby otworzyć ponownie hostowane okno projektu niestandardowego.
Aby utworzyć niestandardowego projektanta działań przy użyciu elementu WorkflowItemsPresenter
Procedura drugiego niestandardowego projektanta działań jest równoległa pierwszy z kilkoma modyfikacjami, z których pierwsza polega na nazwie drugiej aplikacji
UsingWorkflowItemsPresenter
. Ponadto ta aplikacja nie definiuje nowego działania niestandardowego.Kluczowe różnice są zawarte w plikach CustomParallel Projektant.xaml i RehostingWF Projektant.xaml.cs. Oto kod z pliku CustomParallel Projektant.xaml definiujący interfejs użytkownika:
<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>
Oto kod z pliku RehostingWF Projektant.xaml.cs który udostępnia logikę ponownego hostowania:
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()); } } }