2010-04-27 13 views
8

Ho un'attività personalizzata, con un argomento singolo in una stringa. Tuttavia, piuttosto che consentire al designer di inserire una stringa arbitraria, voglio che il designer sia presentato con un Combobox con l'elenco delle opzioni, che le opzioni siano dinamiche e caricate da un database in una raccolta List <>.Associazione di dati a Combobox in Progettazione attività personalizzata

Il mio problema è che non ho idea di come associare il Combobox nella finestra di progettazione a questo elenco e avere la selezione impostata sull'argomento in dell'attività. Visivamente ho il designer di attività che lavora, è solo questo un passo.

+0

Vuoi davvero la vostra attività su misura per avere un'InArgument piuttosto che un immobile? (InArgument pubblico Arg {get; set;} vs. public string Arg {get; set;}) –

+0

@Tim, suppongo che solo una proprietà standard andrebbe bene. –

risposta

7

Normalmente, scriverei l'attività con un property anziché con InArgument. Questo semplifica lo scenario: (. Qui ValidOptions è una certa proprietà della raccolta sulla tua classe ActivityDesigner MyStringProperty qualche get pubblica/set/proprietà sull'attività di base, come:

public string MyStringProperty { get; set; } 

)

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

Il problema che si presenterà se si aggiunge InArgument al mix è che i valori stringa dalla casella combinata non possono essere assegnati direttamente ain attesa di InArgument<string>. Questo è risolvibile usando un custom IValueConverter nel binding.

+0

@Tim, mi dispiace per aver impiegato così tanto tempo a tornare, è stata una settimana frenetica e non ho nemmeno avuto la possibilità di testare questo per confermare che ho capito e che questo si adatta a quello che sto cercando di fare. Non appena lo farò tornerò a segnare come risposta o a sondare ulteriormente il tuo e le comunità! Grazie. –

2

Un modo per risolverlo è definire il proprio ComboBoxEditor che deriva da UITypeEditor. Esporre la collezione si desidera associare questo combobox nella classe di attività e decorare la vostra proprietà associabile in Classe di attività con i seguenti attributi:

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

Anche nel comboboxEditor personalizzato dovrete modificare il vostro EditValue (ITypeDescriptorContext contesto, Metodo IServiceProvider provider, valore dell'oggetto) per ottenere la raccolta e collegarla alla casella combinata.

4

Le risposte precedenti sono utili ma non erano sufficienti per me. Alla fine ho trovato un articolo fantastico dal 2012, nella Guida per gli sviluppatori di .Net 4.5 di Microsoft: Binding a custom activity property to a designer control. Quell'articolo era quasi la risposta completa - tranne un piccolo errore nella classe del convertitore personalizzato, e un grosso difetto: quella tecnica salverà un valore dal ComboBox, ma non lo ripristinerà quando riaprirai il tuo flusso di lavoro.

Microsoft's Ron Jacobs has another answer per progettisti di attività personalizzate. Ho finito per combinare i due per ottenere una soluzione funzionante.

progettazione personalizzata

Il ModelToObjectValueConverter era una risorsa incredibilmente utile, che mi permette di saltare creare il mio IValueConverter. Nello ObjectDataProvider mi vedi caricare un elenco di stringhe chiamando un metodo statico, People.GetPeople(). Il ComboBox si lega a tale provider come sorgente voce, ma si lega il valore selezionato alla proprietà Persona sull'attività personalizzato (in basso)

<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> 

codice personalizzato Attività

Si noti che questo utilizza una proprietà piuttosto di un InArgument, che rende più facile l'associazione del ComboBox.

[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

Ora l'attività personalizzata, CodeActivity1, possono essere trascinati su un flusso di lavoro. Quando si effettua una selezione, il valore selezionato verrà visualizzato nel riquadro delle proprietà. Salva il flusso di lavoro. Chiudi e riapri. Il valore selezionato in precedenza persisterà come desiderato.

screenshot of custom activity designer in action

+0

grazie mille per il tuo bell'esempio! –

Problemi correlati