Привязка данных к Combobox в конструкторе пользовательских действий - PullRequest
9 голосов
/ 27 апреля 2010

У меня есть пользовательское действие с единственным аргументом в виде строки. Однако вместо того, чтобы позволить конструктору вводить произвольную строку, я хочу, чтобы дизайнер был представлен с помощью Combobox со списком параметров, параметры являются динамическими и загружаются из базы данных в коллекцию List <>.

Моя проблема в том, что я понятия не имею, как связать Combobox в конструкторе с этим списком, и в качестве аргумента для выбора выбрано значение in. Визуально у меня работает дизайнер мероприятий, это всего лишь один шаг.

Ответы [ 3 ]

7 голосов
/ 29 апреля 2010

Обычно, я бы записал активность с property вместо InArgument. Это упрощает сценарий:

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

(здесь ValidOptions - это некоторое свойство Collection в вашем классе ActivityDesigner. MyStringProperty - это некоторое общедоступное свойство get / set / для базовой операции, например:

public string MyStringProperty { get; set; }

)

Проблема, с которой вы столкнетесь, если добавите в смесь InArgument, состоит в том, что строковые значения из поля со списком нельзя напрямую назначить ModelItem, ожидающему InArgument<string>. Это можно исправить с помощью пользовательского IValueConverter в привязке.

4 голосов
/ 26 марта 2014

Предыдущие ответы полезны, но мне их было недостаточно. В конце концов я нашел потрясающую статью 2012 года в Руководстве разработчика по .Net 4.5 от Microsoft: Привязка свойства пользовательского действия к элементу управления конструктора . Эта статья была почти полным ответом - за исключением незначительной ошибки в пользовательском классе конвертера и серьезного недостатка: этот метод сохранит значение из ComboBox, но не восстановит его, когда вы снова откроете свой рабочий процесс.

Рон Джейкобс (Microsoft) предлагает другой ответ для разработчиков пользовательских заданий. В итоге я объединила их, чтобы получить рабочее решение.

Пользовательский конструктор

ModelToObjectValueConverter был невероятно полезным ресурсом, позволившим мне пропустить создание моего IValueConverter. В ObjectDataProvider вы видите, как я загружаю список строк, вызывая статический метод People.GetPeople(). ComboBox привязывается к этому провайдеру в качестве источника элемента, но привязывает выбранное значение к свойству Person в пользовательском действии (ниже)

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

Код активности пользователя

Обратите внимание, что здесь используется свойство, а не InArgument, что облегчает привязку 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

Теперь пользовательское действие, CodeActivity1, можно перетащить в рабочий процесс. Когда вы сделаете выбор, выбранное значение появится на панели свойств. Сохраните рабочий процесс. Закройте и снова откройте. Ранее выбранное значение будет сохраняться по желанию.

screenshot of custom activity designer in action

2 голосов
/ 11 апреля 2011

Один из способов ее решения - определить свой собственный ComboBoxEditor, производный от UITypeEditor. Откройте коллекцию, которую вы хотите связать, этот комбинированный список в классе активности и украсьте свойство привязки в классе Activity следующим атрибутом:

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

Также в пользовательском comboboxEditor вам нужно будет изменить свой Метод EditValue (контекст ITypeDescriptorContext, поставщик IServiceProvider, значение объекта) для получения коллекции и ее привязки к комбинированному списку.

...