У меня проблемы с получением проверки правильности работы в конструкторе для моей пользовательской активности.Простейший пример для воспроизведения поведения следующий:
У меня есть пользовательское действие WF4 с динамическим набором аргументов, хранящихся в словаре:
[Designer(typeof(DictionaryActivityDesigner))]
public class DictionaryActivity : NativeActivity
{
[Browsable(false)]
public Dictionary<string, InArgument> Arguments { get; set; }
public InArgument<string> StringArg { get; set; }
public DictionaryActivity()
{
Arguments = new Dictionary<string, InArgument>();
}
protected override void Execute(NativeActivityContext context)
{ }
}
В конструкторе я динамически создаю выражениетекстовые поля для редактирования этих аргументов.Пользователь имеет возможность определять аргументы и их типы в отдельном модальном окне, но для простоты я исправил аргументы в этом примере:
public partial class DictionaryActivityDesigner
{
private Dictionary<string, Type> definition;
public DictionaryActivityDesigner()
{
definition = new Dictionary<string, Type>
{
{ "String Arg", typeof(string) },
{ "Int Arg", typeof(int) }
};
InitializeComponent();
}
public void InitializeGrid(Dictionary<string, Type> arguments)
{
ArgumentsGrid.RowDefinitions.Clear();
ArgumentsGrid.Children.Clear();
int gridRow = 0;
foreach (var arg in arguments)
{
ArgumentsGrid.RowDefinitions.Add(new RowDefinition());
var label = new Label()
{
Content = arg.Key + ":"
};
Grid.SetRow(label, gridRow);
Grid.SetColumn(label, 0);
ArgumentsGrid.Children.Add(label);
var textbox = new ExpressionTextBox()
{
ExpressionType = arg.Value,
OwnerActivity = ModelItem,
UseLocationExpression = false
};
var binding = new Binding()
{
Mode = BindingMode.TwoWay,
Converter = new ArgumentToExpressionConverter(),
ConverterParameter = "In",
Path = new PropertyPath("ModelItem.Arguments[(0)]", arg.Key)
};
textbox.SetBinding(ExpressionTextBox.ExpressionProperty, binding);
Grid.SetRow(textbox, gridRow);
Grid.SetColumn(textbox, 1);
ArgumentsGrid.Children.Add(textbox);
gridRow++;
}
}
private void ActivityDesigner_Loaded(object sender, RoutedEventArgs e)
{
InitializeGrid(definition);
}
}
Ниже приведен XAML для конструктора:
<sap:ActivityDesigner x:Class="ActivityValidation.DictionaryActivityDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
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"
Loaded="ActivityDesigner_Loaded">
<sap:ActivityDesigner.Resources>
<ResourceDictionary>
<sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
</ResourceDictionary>
</sap:ActivityDesigner.Resources>
<StackPanel Orientation="Vertical">
<Grid Name="ArgumentsGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MinWidth="250" />
</Grid.ColumnDefinitions>
</Grid>
<sapv:ExpressionTextBox ExpressionType="s:String"
OwnerActivity="{Binding ModelItem}"
Expression="{Binding ModelItem.StringArg, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}" />
</StackPanel>
</sap:ActivityDesigner>
Метод InitializeGrid
добавляет текстовые поля выражений для аргументов в ArgumentGrid
.Под ним у меня есть отдельное статически определенное текстовое поле выражения для фиксированного аргумента в упражнении, чтобы продемонстрировать (почти) желаемое поведение.
Теперь к задачам:
Неверные выражения для динамических аргументов приводят только к тому, что значок ошибки появляется рядом с текстовым полем, но не распространяется на верхнюю панель конструктора, как это происходит при наличии ошибки в статически определенном текстовом поле.
Если я закрою конструктор в таком недопустимом состоянии (и сохраню определение), значок ошибки корректно распространяется на верхнюю панель, даже если ошибка присутствует только в динамическом текстовом поле.Хотя потом поведение становится еще более странным.После изменения значений аргументов теперь даже значок ошибки рядом с текстовым полем перестает работать согласованно.
Если я полностью удаляю содержимое динамического текстового поля,значение в словаре устанавливается равным нулю, что проявляется в определении рабочего процесса как <x:Null x:Key="String Arg" />
вместо <InArgument x:TypeArguments="x:String" x:Key="String Arg">["a"]</InArgument>
или просто пропускает запись, как в случае до редактирования выражения в первый раз.Если я снова открою такой рабочий процесс, даже статически созданное текстовое поле больше не будет работать должным образом (значок ошибки отображается только тогда, когда текстовое поле находится в фокусе и больше не распространяется на верхнюю часть).
Кажется очевидным, что я делаю что-то не так при создании динамических текстовых полей.Каков будет правильный способ сделать это?Есть ли какой-нибудь пример для создания конструктора для пользовательского действия с динамическим числом аргументов?
РЕДАКТИРОВАТЬ:
Для тех, кто заинтересован: