Ошибка привязки в конструкторе операций с использованием ActivityFunc <> - PullRequest
0 голосов
/ 08 октября 2011

Мне трудно заставить моего собственного дизайнера действий отображаться в конструкторе рабочих процессов.Моя деятельность включает в себя функцию активности, и я уже нашел несколько сообщений в блогах, посвященных этим вопросам здесь , здесь , здесь и здесь .

Настраиваемое действие имеет ActivityFunc<> в качестве входного аргумента, и мне нужно представить функцию в конструкторе как зону перетаскивания, в которую пользователь может поместить «внутреннее» действие ( TransactionScope).

Пользовательское действие создано в XAML, и объявление функции выглядит следующим образом:

<x:Property Name="CompletionTest" Type="ActivityFunc(sdscmt:DmeTask, sdsav:WfPatient, sdscmc:DmeClinicalElement, x:Boolean)" />

XAML также содержит действие InvokeFunc<>соответствует свойству CompletionTest.

Дизайнер действий следует рекомендациям, изложенным в сообщениях в блоге, упомянутых выше.В частности, он переопределяет OnModelItemChanged для инициализации свойства CompletionTest:

if (this.ModelItem.Properties["CompletionTest"].Value == null)
{
    this.ModelItem.Properties["CompletionTest"].SetValue(
        new ActivityFunc<DmeTask, WfPatient, DmeClinicalElement, bool>()
        {
            Argument1 = new DelegateInArgument<DmeTask>
            {
                Name = "task"
            },
            Argument2 = new DelegateInArgument<WfPatient>
            {
                Name = "patient"
            },
            Argument3 = new DelegateInArgument<DmeClinicalElement>
            {
                Name = "element"
            },
            Result = new DelegateOutArgument<bool>
            {
                Name = "success"
            },
        });
}

XAML конструктора выглядит так:

<sap:ActivityDesigner x:Class="SoftInfo.Dme.ServicesDme.Workflow.Design.PerformTaskDesigner" ... >
    <StackPanel>
        <sap:WorkflowItemPresenter AllowedItemType="{x:Type sa:Activity}" Background="Transparent" MinWidth="150" MinHeight="100" HintText="Drop the completion test here" Margin="5,5,5,5" Item="{Binding Path=ModelItem.CompletionTest.Handler, Mode=TwoWay}" />
    </StackPanel>
</sap:ActivityDesigner>

После всего этого всякий раз, когда я размещаю экземпляриз моего пользовательского действия в рабочий процесс, я получаю красное поле с надписью «Не удалось создать представление для PerformTask», где должен появиться мой дизайнер.Всплывающая подсказка окна указывает, что в конструкторе произошло исключение:

    System.Windows.Markup.XamlParseException: A 'Binding' cannot be set on the 'Item' property of type 'WorkflowItemPresenter'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

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

1 Ответ

0 голосов
/ 08 октября 2011

Это своего рода запутанный способ сделать это.Ошибка может быть неверной;внутреннее исключение расскажет историю, которую я поставил бы (извините, слушая «Игру престолов», пока я работаю сегодня).

Я реализую IActivityTemplateFactory для настройки моих делегатов активности:

public sealed class MyActivity: NativeActivity, IActivityTemplateFactory
{
    public const string ChildArgumentName = "theArgument";

    public ActivityFunc<object, bool> Child { get; set; }

    Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
    {
        return new MyActivity()
        {
            Child = new ActivityFunc<Capture, bool>
            {
                Argument = new DelegateInArgument<object>(ChildArgumentName )
            }
        };
    }
}

Обратите внимание на пару вещей здесь.Да, область разработки создает экземпляр вашей деятельности только для того, чтобы использовать его для создания другого экземпляра той же операции (конечно, правильно настроенного), но этот метод является пуленепробиваемым.Вы можете, если этого требуют требования, перенести вашу реализацию IATF в другое место, но если это не имеет значения, кого это волнует?

Обратите внимание, что я объявляю в своем проекте Activity, каким будет имя аргумента Func.Вы можете сделать это более общим способом (пользовательские атрибуты и т. Д.), Но если ваши действия соответствуют предсказуемым образом, я обнаружил, что это самый простой способ автоматически связать дочерние действия с их родителями.YMMV.

В конструкторе это похоже:

<sap:WorkflowItemPresenter
    HintText="Add child here"
    Item="{Binding ModelItem.Child.Handler}" />

это все, что вам нужно.Если подпись Действия не совпадает, это не будет соответствовать.Ребенок также использует IATF, чтобы связать себя со своим родителем:

public sealed class ChildActivity : NativeActivity<bool>, IActivityTemplateFactory
{
    public InArgument<object> Target { get; set; }

    Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
    {
        return new ChildActivity
        {
            Target = new VisualBasicValue<object>(MyActivity.ChildArgumentName)
        };
    }
 }

Если вы ожидаете, что активность вашего ребенка будет отброшена на другие цели, вам, возможно, придется провести досадную проверку target DependencyObject, что позволит вам проверить текущее дерево рабочего процесса.(Обратите внимание, я не на 100% знаком с неявным поведением преобразования VisualBasicValue, поэтому у вас могут быть некоторые ошибки компилятора с приведенным выше кодом!)

Другой вариант, если вам нужно быть слишком хитрым (оставьтеАктивность из панели инструментов, а затем перетащите ее куда-нибудь еще, где вам придется заново выполнить проверку), чтобы проверить текущее состояние рабочего процесса из CacheMetadata.Я этого не делал, но, полагаю, вы можете обновить свои регистрации с помощью области дизайна, чтобы отразить текущее состояние рабочего процесса.

...