Procedura: Creare un ActivityDesigner personalizzato

Gli ActivityDesigner personalizzati vengono in genere implementati in modo che le attività associate siano componibili con altre attività le cui finestre di progettazione possono essere rilasciate sull'area di progettazione insieme ad esse. Questa funzionalità richiede che una finestra di progettazione attività personalizzata fornisca una "zona a discesa" in cui è possibile inserire un'attività arbitraria e anche i mezzi per gestire la raccolta risultante di elementi nell'area di progettazione. In questo argomento viene descritto come creare un ActivityDesigner personalizzato contenente tale area di rilascio e come creare un ActivityDesigner personalizzato che fornisca la funzionalità di modifica necessaria per gestire la raccolta di elementi della finestra di progettazione.

L'ActivityDesigner personalizzato eredita in genere da ActivityDesigner che è il tipo di ActivityDesigner di base predefinito per qualsiasi attività senza una finestra di progettazione specifica. Questo tipo fornisce una fase di progettazione per l'interazione con la griglia delle proprietà e per la configurazione degli aspetti di base, ad esempio la gestione di colori e icone.

L'oggetto ActivityDesigner usa due controlli di supporto, WorkflowItemPresenter e WorkflowItemsPresenter, per facilitare lo sviluppo di ActivityDesigner personalizzati. Questi consentono di gestire funzionalità comuni quali il trascinamento e rilascio di elementi figlio, l'eliminazione, la selezione nonché l'aggiunta di tali elementi figlio. Consente WorkflowItemPresenter un singolo elemento dell'interfaccia utente figlio all'interno, fornendo la "zona a discesa", mentre può WorkflowItemsPresenter fornire supporto di più elementi dell'interfaccia utente, incluse funzionalità aggiuntive come l'ordinamento, lo spostamento, l'eliminazione e l'aggiunta di elementi figlio.

L'altra parte chiave della storia che richiede l'evidenziazione nell'implementazione di un progettazione attività personalizzata riguarda il modo in cui le modifiche visive sono associate usando l'associazione di dati WPF all'istanza archiviata in memoria di ciò che si sta modificando nella finestra di progettazione. Questa operazione viene eseguita dall'albero degli elementi del modello che è inoltre responsabile per l'abilitazione della notifica di modifiche e il rilevamento di eventi quali le modifiche degli stati.

In questo argomento vengono delineate due procedure.

  1. Nella prima viene descritto come creare un ActivityDesigner personalizzato con un oggetto WorkflowItemPresenter che fornisce l'area di rilascio che riceve altre attività. Questa procedura si basa sull'esempio personalizzato progettazione composita - Relatorer elemento del flusso di lavoro .

  2. Nella seconda viene descritto come creare un ActivityDesigner personalizzato con un WorkflowItemsPresenter che fornisce la funzionalità necessaria per modificare una raccolta di elementi contenuti. Questa procedura si basa sull'esempio personalizzato progettazione composita - Elementi del flusso di lavoro Relatorer .

Per creare un ActivityDesigner personalizzato con un'area di rilascio usando WorkflowItemPresenter

  1. Avviare Visual Studio 2010.

  2. Scegliere Nuovo dal menu File e quindi selezionare Project....

    Verrà visualizzata la finestra di dialogo Nuovo progetto .

  3. Nel riquadro Modelli installati selezionare Windows dalla categoria di lingua preferita.

  4. Nel riquadro Modelli selezionare Applicazione WPF.

  5. Nella casella Nome immettere UsingWorkflowItemPresenter.

  6. Nella casella Percorso immettere la directory in cui si vuole salvare il progetto oppure fare clic su Sfoglia per spostarsi.

  7. Nella casella Soluzione accettare il valore predefinito.

  8. Fare clic su OK.

  9. Fare clic con il pulsante destro del mouse sul file MainWindows.xaml nella Esplora soluzioni, selezionare Elimina e confermare OK nella finestra di dialogo Microsoft Visual Studio.

  10. Fare clic con il pulsante destro del mouse sul progetto UsingWorkflowItemPresenter in Esplora soluzioni, selezionare Aggiungi, quindi Nuovo elemento per visualizzare la finestra di dialogo Aggiungi nuovo elemento e selezionare la categoria WPF nella sezione Modelli installati a sinistra.

  11. Selezionare il modello Window (WPF), denominarlo RehostingWFDesignere fare clic su Aggiungi.

  12. Aprire il file RehostingWFDesigner.xaml e incollare il codice seguente per definire l'interfaccia utente per l'applicazione:

    <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. Per associare un ActivityDesigner a un tipo di attività, è necessario registrare tale ActivityDesigner con l'archivio dei metadati. A tal fine, aggiungere il metodo RegisterMetadata alla classe RehostingWFDesigner. Nell'ambito del RegisterMetadata metodo creare un AttributeTableBuilder oggetto e chiamare il AddCustomAttributes metodo per aggiungerli. Chiamare il metodo AddAttributeTable per aggiungere l'oggetto AttributeTable all'archivio dei metadati. Il codice seguente contiene la logica di riallocazione per la finestra di progettazione. Registra i metadati, inserisce SimpleNativeActivity nella casella degli strumenti e crea il flusso di lavoro. Inserire questo codice nel file 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. Fare clic con il pulsante destro del mouse sulla directory Riferimenti in Esplora soluzioni e scegliere Aggiungi riferimento ... per visualizzare la finestra di dialogo Aggiungi riferimento.

  15. Fare clic sulla scheda .NET , individuare l'assembly denominato System.Activities.Core.Presentation, selezionarlo e fare clic su OK.

  16. Tramite la stessa procedura aggiungere riferimenti agli assembly indicati di seguito:

    1. System.Data.DataSetExtensions.dll

    2. System.Activities.Presentation.dll

    3. System.ServiceModel.Activities.dll

  17. Aprire il file App.xaml e modificare il valore di StartUpUri in "RehostingWFDesigner.xaml".

  18. Fare clic con il pulsante destro del mouse sul progetto UsingWorkflowItemPresenter in Esplora soluzioni, selezionare Aggiungi, quindi Nuovo elemento per visualizzare la finestra di dialogo Aggiungi nuovo elemento e selezionare la categoria Flusso di lavoro nella sezione Modelli installati a sinistra.

  19. Selezionare il modello di Activity Designer , denominarlo SimpleNativeDesignere fare clic su Aggiungi.

  20. Aprire il file SimpleNativeDesigner.xaml e incollarne il codice seguente. Questo codice usa ActivityDesigner come elemento radice e illustra come usare l'associazione per integrare WorkflowItemPresenter nella finestra di progettazione in modo da poter visualizzare un tipo figlio nel CompositeActivityDesigner.

    Nota

    Lo schema dell'oggetto ActivityDesigner consente di aggiungere un unico elemento figlio alla definizione dell'ActivityDesigner personalizzato. Questo elemento, tuttavia, potrebbe essere un oggetto StackPanel, Grid o un altro elemento composito dell'interfaccia utente.

    <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. Fare clic con il pulsante destro del mouse sul progetto UsingWorkflowItemPresenter in Esplora soluzioni, selezionare Aggiungi, quindi Nuovo elemento per visualizzare la finestra di dialogo Aggiungi nuovo elemento e selezionare la categoria Flusso di lavoro nella sezione Modelli installati a sinistra.

  22. Selezionare il modello attività codice , denominarlo SimpleNativeActivitye fare clic su Aggiungi.

  23. Implementare la classe immettendo il SimpleNativeActivity codice seguente nel file 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. Selezionare Compila soluzione dal menu Compila .

  25. Selezionare Avvia senza debug dal menu Debug per aprire la finestra di progettazione personalizzata rehosted.

Per creare un ActivityDesigner personalizzato usando WorkflowItemsPresenter

  1. La procedura per la seconda finestra di progettazione attività personalizzata è la prima con alcune modifiche, la prima di cui è assegnare il nome alla seconda applicazione UsingWorkflowItemsPresenter. Questa applicazione non definisce inoltre una nuova attività personalizzata.

  2. Le differenze principali sono contenute nei file CustomParallelDesigner.xaml e RehostingWFDesigner.xaml.cs . Ecco il codice del file CustomParallelDesigner.xaml che definisce l'interfaccia utente:

    <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. Ecco il codice del file RehostingWFDesigner.xaml.cs che fornisce la logica di rehosting:

    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());
            }
        }
    }
    

Vedi anche