在对话框中使用时如何配置 ExpressionTextBox 绑定/OwnerActivity?

How to configure ExpressionTextBox bindings / OwnerActivity when used in a dialog?

我们的小组正在围绕我们的电子邮件 activity 开发自定义 Activity 设计器。这是一个非常直接的设计器,允许用户输入设置/凭据,但我们考虑将一些设置放在对话框中 window,而不是用所有可设置的选项使 activity 设计器变得混乱。 (当您单击服务器地址框旁边的按钮时打开)。

我们的一些电子邮件 activity 属性是 InArguments 因此我们尝试使用 ExpressionTextBox 来显示这些值但运气不佳。主要问题是我们不确定如何在 ExpressionTextBox 上正确设置绑定和 OwnerActivity。在 Activity Designer 的 xaml 中,这只需使用 InArgument 的转换器设置 Expression=ModelItem.Property 并设置 OwnerActivity=ModelItem 即可完成,如下所示:

<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="{Binding ModelItem.ServerAddress, ConverterParameter=In, Converter={StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="{x:Type system:String}" OwnerActivity="{Binding ModelItem}" Margin="2" MaxLines="1" />

如果有人对我们如何在对话中完成此操作有任何想法,请提出建议。

嗯,这比 WF4 更 WPF\MVVM 问题,真的。

开发自定义活动设计器时,您只需牢记一件事:在 designer\dialog 上所做的任何更改都应反映在 ModelItem 上。 通过 XAML 绑定表达式或通过 ModelItem.Properties 属性.

上的代码

现在,您何时以及如何做,有几个答案,但这实际上是一个实施细节,取决于您想要如何做。

假设您在单击按钮旁边的服务器地址框 时显示对话框。并假设您可以通过名称访问对话框文本框。届时,您可以访问 ModelItem,因此只需根据需要设置其属性即可:

private void ButtonNextToServerAddressBox_OnClick(object sender, RoutedEventArgs e) 
{
    var dialog = new ServerAddressEditor();
    var result = dialog.ShowDialog();

    if (result ?? false) 
    {
        ModelItem.Properties["Server"].SetValue(new InArgument<string>(dialog.ServerTextBox.Text));
        ModelItem.Properties["Port"].SetValue(new InArgument<string>(dialog.PortTextBox.Text));
        // ... set all other properties
    }
}

现在,如果您使用任何其他模式,或者您想要纯 MVVM,由于 ModelItem 的工作方式,它可能会更棘手一些。但这是一个完全好的方法。

我通过在对话框的 ViewModel 中创建一个 属性 来保存 Activity Designer 的 ModelItem 来解决这个问题。

public ModelItem OwnerActivity {
    get { return _OwnerActivity; }
    set { _OwnerActivity = value; }
}

vm.OwnerActivity = this.DataContext.ModelItem;

然后我将对话框中表达式文本框的 Xaml 设置为绑定到此:

<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="
    {Binding Path=OwnerActivity.ServerAddress, ConverterParameter=In, Converter=
    {StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="
    {x:Type system:String}" OwnerActivity="{Binding OwnerActivity}" Margin="2" 
    MaxLines="1" />

因为我现在直接绑定到来自 Activity 设计器的 ModelItem,所以从对话框 属性 对 ModelItem 所做的任何更改总是提交,即使您从对话。为了连接 Ok/Cancel 按钮以便它们相应地工作,我在对话框中执行了以下操作:

// declare a ModelEditingScope to make changes transactional
private ModelEditingScope _editScope;

// add this to the constructor of the dialog to begin transactional edits on the ModelItem 
_editScope = editorViewModel.OwnerActivity.BeginEdit();

// ok & cancel button click event to commit or revert the changes.
private void OK_Click(object sender, RoutedEventArgs e)
{
    _editScope.Complete();
    this.DialogResult = DialogResult.OK;
    this.Close();
}    
private void Cancel_Click(object sender, RoutedEventArgs e)
{
    _editScope.Revert();
    this.DialogResult = DialogResult.Cancel;
    this.Close()
}