2010-04-27 12 views
8

Tengo una actividad personalizada, con un solo argumento que es una cadena. Sin embargo, en lugar de permitir que el diseñador ingrese una cadena arbitraria, quiero que el diseñador se presente con un Combobox con la lista de opciones, las opciones son dinámicas y se cargan desde una base de datos en una colección List <>.Enlazar datos a Combobox en el diseñador de actividad personalizado

Mi problema es que no tengo ni idea de cómo vincular el Combobox en el diseñador a esta lista y hacer que la selección se establezca en el argumento de la actividad. Visualmente tengo el diseñador de actividades trabajando, es solo este paso.

+0

¿Realmente quiere que su actividad personalizada para tener una InArgument en lugar de una propiedad? (public InArgument Arg {get; set;} vs. cadena pública Arg {get; set;}) –

+0

@Tim, supongo que solo una propiedad estándar estaría bien también. –

Respuesta

7

Normalmente, escribo la actividad con un property en lugar de un InArgument. Esto simplifica el escenario: (. Aquí ValidOptions es alguna propiedad de colección en su clase ActivityDesigner MyStringProperty es algunos se ponen pública/set/propiedad en la actividad subyacente, como:

public string MyStringProperty { get; set; } 

)

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

El problema que tendrá si agrega InArgument a la mezcla es que los valores de cadena del cuadro combinado no se pueden asignar directamente a ModelItem esperando InArgument<string>. Esto se puede reparar usando un IValueConverter personalizado en su enlace.

+0

@Tim, perdón por tardar tanto en regresar, ha sido una semana agitada y ni siquiera he tenido la oportunidad de probar esto para confirmar que entiendo y que esto se ajusta a lo que estoy tratando de hacer. Tan pronto como lo haga, volveré para marcar como respondido o para sondear tu cerebro y el de las comunidades. Gracias. –

2

Una forma de resolverlo es definir su propio ComboBoxEditor que se deriva de UITypeEditor. Exponer la colección que desea enlazar este cuadro combinado en la clase de actividad y decorar su propiedad enlazable en la clase de actividad con los siguientes atributos:

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

También en el comboboxEditor personalizada que tendrá que modificar su EditValue (ITypeDescriptorContext contexto, Método IServiceProvider, valor del objeto) para obtener la colección y vincularla al cuadro combinado.

4

Las respuestas anteriores son útiles, pero no fueron suficientes para mí. Eventualmente encontré un excelente artículo de 2012 en Microsoft .Net 4.5 Developer Guide: Binding a custom activity property to a designer control. Ese artículo fue casi la respuesta completa, excepto por un error menor en la clase de convertidor personalizado, y un defecto importante: esa técnica guardará un valor del ComboBox, pero no lo restaurará cuando vuelva a abrir su flujo de trabajo.

Ron Jacobs de Microsoft has another answer para diseñadores de actividades personalizadas. Terminé combinando los dos para obtener una solución de trabajo.

encargo del diseñador

El ModelToObjectValueConverter era un recurso increíblemente útil, lo que me permite crear mi propio salto IValueConverter. En el ObjectDataProvider me ves cargando una lista de cadenas llamando a un método estático, People.GetPeople(). El cuadro combinado se une a ese proveedor como el origen de elementos, pero se une el valor seleccionado para la propiedad persona en la actividad personalizada (continuación)

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

código personalizado Actividad

Tenga en cuenta que este utiliza una propiedad en lugar que un InArgument, que facilita la unión 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);  
    } 
} 

flujo de trabajo

Ahora la actividad personalizada, CodeActivity1, se pueden arrastrar a un flujo de trabajo. Cuando haga una selección, el valor seleccionado aparecerá en el panel de propiedades. Guarde el flujo de trabajo. Cierra y vuelve a abrir. El valor seleccionado previamente persistirá según lo deseado.

screenshot of custom activity designer in action

+0

muchas gracias por su buen ejemplo! –

Cuestiones relacionadas