2010-04-27 16 views
8

Ich habe eine benutzerdefinierte Aktivität mit einem einzelnen Argument, das eine Zeichenfolge ist. Anstatt dem Designer jedoch die Eingabe einer beliebigen Zeichenfolge zu erlauben, möchte ich dem Designer eine Combobox mit der Optionsliste präsentieren. Die Optionen sind dynamisch und werden aus einer Datenbank in eine Liste <> Sammlung geladen.Daten an Combobox im benutzerdefinierten Aktivitätsdesigner binden

Mein Problem ist, ich habe keine Ahnung, wie Sie die Combobox im Designer an diese Liste binden und die Auswahl auf das In-Argument der Aktivität festgelegt haben. Visuell habe ich den Aktivitätsdesigner am arbeiten, es ist nur dieser eine Schritt.

+0

Wollen Sie wirklich Ihre benutzerdefinierte Aktivität eine InArgument eher als eine Eigenschaft haben? (public InArgument Arg {get; set;} vs. öffentliche Zeichenkette Arg {get; set;}) –

+0

@Tim, ich denke nur eine Standard-Eigenschaft wäre auch in Ordnung. –

Antwort

7

Normalerweise würde ich die Aktivität mit einem property anstatt einem InArgument schreiben. Dies vereinfacht das Szenario: (. Hier ValidOptions einige Sammlung Eigentum auf Ihrer Activity Klasse MyStringProperty ist einige öffentliche get/set/Eigenschaft auf die zugrunde liegende Tätigkeit wie:

public string MyStringProperty { get; set; } 

)

<ComboBox ItemsSource="{Binding Path=ValidOptions}" 
SelectedValue="{Binding Path=ModelItem.MyStringProperty, Mode=TwoWay}"/> 

Das Problem, das Sie haben, wenn Sie InArgument zu der Mischung hinzufügen, ist, dass die Zeichenfolgenwerte aus dem Kombinationsfeld nicht direkt einer ModelItem erwarteten InArgument<string> zugeordnet werden können. Dies ist mit einem benutzerdefinierten IValueConverter in Ihrer Bindung reparierbar.

+0

@Tim, tut mir leid, dass ich so lange gebraucht habe, um zurück zu kommen, es war eine hektische Woche und ich hatte nicht einmal die Chance, dies zu testen, um zu bestätigen, dass ich verstehe und dass dies zu dem passt, was ich versuche. Sobald ich das tue, werde ich entweder zurückkommen, um als beantwortet zu markieren oder dein Gehirn und das Gehirn der Gemeinschaft weiter zu untersuchen! Vielen Dank. –

2

Eine Möglichkeit, dies zu lösen, besteht darin, einen eigenen ComboBoxEditor zu definieren, der von UITypeEditor abgeleitet ist. Expose die Sammlung Sie diese Combobox in der Aktivitätsklasse binden möchten und Ihre bindbare Eigenschaft in Aktivitätsklasse dekorieren mit folgenden Attribut:

[EditorAttribute(typeof(CustomListBoxEditor), typeof(System.Drawing.Design.UITypeEditor))] 

Auch in der benutzerdefinierten comboboxEditor müssen Sie Ihre EditValue (ITypeDescriptorContext Kontext ändern, IServiceProvider provider, object value), um die Sammlung abzurufen und an die Combobox zu binden.

4

Die vorherigen Antworten sind hilfreich, aber waren nicht genug für mich. Schließlich fand ich einen tollen Artikel von 2012 in Microsofts .Net 4.5 Entwicklerhandbuch: Binding a custom activity property to a designer control. Dieser Artikel war fast die vollständige Antwort - abgesehen von einem kleineren Fehler in der benutzerdefinierten Konverterklasse und einem großen Fehler: Diese Technik speichert einen Wert aus der ComboBox, aber er wird ihn nicht wiederherstellen, wenn Sie Ihren Workflow erneut öffnen.

Microsoft Ron Jacobs has another answer für benutzerdefinierte Aktivitäten Designer. Ich habe die beiden kombiniert, um eine funktionierende Lösung zu bekommen.

Custom-Designer

Die ModelToObjectValueConverter war eine unglaublich hilfreiche Ressource, so dass ich meine eigenen IValueConverter überspringen zu schaffen. Im ObjectDataProvider sehen Sie, dass ich eine Liste von Strings durch Aufruf einer statischen Methode, People.GetPeople(), lade. Die ComboBox bindet an diesen Anbieter als Nachrichtenquelle, sondern bindet den ausgewählten Wert an der Person Eigenschaft auf der benutzerdefinierte Aktivität (unten)

<sap:ActivityDesigner x:Class="ActivityLibrary1.ComboBoxActivityDesigner" 
    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:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation" 
    xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation" 
    xmlns:c="clr-namespace:ActivityLibrary1"> 

    <sap:ActivityDesigner.Resources> 
     <ResourceDictionary> 
      <sapc:ModelToObjectValueConverter x:Key="ModelToObjectValueConverter" /> 
      <ObjectDataProvider x:Key="people" ObjectType="{x:Type c:People}" MethodName="GetPeople"/> 
     </ResourceDictionary> 
    </sap:ActivityDesigner.Resources> 

    <Grid> 
     <Label Content="Person" HorizontalAlignment="Left" VerticalAlignment="Top" /> 
     <ComboBox HorizontalAlignment="Left" 
        Margin="66,0,0,0" 
        VerticalAlignment="Top" 
        Width="120" 
        SelectedValue="{Binding Path=ModelItem.Person, Mode=TwoWay, Converter={StaticResource ModelToObjectValueConverter} }" 
        ItemsSource="{Binding Source={StaticResource people}}"> 
     </ComboBox> 
    </Grid> 
</sap:ActivityDesigner> 

Custom Code Aktivität

Beachten Sie, dass dies eine Eigenschaft verwendet, eher als ein InArgument, das das Kombinieren der ComboBox erleichtert.

[Designer(typeof(ComboBoxActivityDesigner))] 
public class CodeActivity1 : CodeActivity 
{  
    public string Person { get; set; } 

    protected override void Execute(CodeActivityContext context) 
    { 
     // Just to demonstrate that it worked 
     MessageBox.Show(Person);  
    } 
} 

Workflow-

Nun ist die benutzerdefinierte Aktivität, CodeActivity1, kann auf einen Workflow gezogen werden. Wenn Sie eine Auswahl treffen, wird der ausgewählte Wert im Eigenschaftenbereich angezeigt. Speichern Sie den Workflow. Schließen und erneut öffnen. Der zuvor ausgewählte Wert bleibt wie gewünscht erhalten.

screenshot of custom activity designer in action

+0

vielen dank für ihr schönes beispiel! –