workflow-foundation-4 - 在代码中更新 DisplayName,未显示在设计器中?

标签 workflow-foundation-4 activitydesigner

这应该是一个简单的问题,但我不明白。当我的自定义事件的某些属性发生更改(例如,通过在 WF 设计器的属性网格中更改它)时,我想动态更新 DisplayName。我在属性 setter 代码中执行此操作:

public sealed class TarpSpecItem : Activity, ITarpSpecItem, INotifyPropertyChanged
{
...
    public DocumentationType Type
    {
        get { return _type; }
        set { _type = value;
            DisplayName = "<" + value.ToString() + ">";
            OnPropertyChanged("DisplayName");
            OnPropertyChanged("Type");
        }
    }

该事件实现 INotifyPropertyChanged。然而,DisplayName 在设计器表面上并没有改变。我错过了什么?


威尔的回答是正确的。我将设计器 *.xaml.cs 的更新代码粘贴在这里作为单独的答案,以具有正确的格式(不可能作为注释)。这段代码可以编译并完成任务。

    protected override void OnModelItemChanged(object newItem)
    {
        ModelItem modelItem = newItem as ModelItem;
        if (modelItem != null)
            modelItem.PropertyChanged += this.ModelItemPropertyChangedHandler;
        base.OnModelItemChanged(newItem);
    }

    private void ModelItemPropertyChangedHandler(object sender, PropertyChangedEventArgs e)
    {
        if (!e.PropertyName.Equals("Type", StringComparison.OrdinalIgnoreCase))
            return;
        ModelItem.Properties["DisplayName"].SetValue("<" + ModelItem.Properties["Type"].Value +">");
    }

将事件包装在模型项内并不会使解决方案变得显而易见,不是吗?很难看出发生了什么,但它确实有效。干得好,威尔!

最佳答案

您的Activity 包含在 ModelItem 中,它处理 Activity 和设计界面之间的所有通知服务。

最初包装在设计器中时,ModelItem 不会检查您的 Activity 以查看它是否提供某些属性更改通知方法 (INPC 、自定义 TypeDescriptor 等)或其他接口(interface)(即 IDataErrorInfo,我有一个连接 here )。

因此,本质上,您无法在这里完成您想要完成的任务。从 Activity 内部,您无法通过包装 ModelItem 发回更改通知。无论如何,你确实不应该这样做。

在设计器中,状态更改应该通过ModelItem,因为它需要保持其状态与包装的Activity同步。如果其状态和包装实例的状态不一致,您将无法在设计器中看到正确的信息。

// we're doing this in the designer
var activity = ModelItem.GetCurrentValue() as MyActivity; 
activity.DisplayName = "You won't ever see this in the design surface!";

相反,您必须通过 ModelItem 进行代码更改

// again, in the designer code
ModelItem.Properties["DisplayName"].Value = "You will see this change!";

那么,解决办法是什么?唯一真正的解决方案是确保您的Activity在状态更改时处于被动状态!属性值更改不应触发任何事情

相反,请将这样的代码移至设计器中!

override OnModelItemChanged(object obj)
{
    // live dangerously!
    var mi = obj as ModelItem;
    mi.PropertyChanged += OnPropertyChanged;
}

void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if(!e.PropertyName.Equals("Type", StringComparison.OrdinalIgnoreCase))
        return;
    ModelItem.Properties["DisplayName"].Value = 
        "<" + 
        ModelItem.Properties["Type"].GetCurrentValue().ToString() + 
        ">";
}

当然,你不能只是复制粘贴这个。它可能有一些错误。但它让你知道你必须做什么。

关于workflow-foundation-4 - 在代码中更新 DisplayName,未显示在设计器中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15910548/

相关文章:

c# - 在不知道事件的具体类型的情况下恢复持久的 Window Workflow 4 事件

workflow-foundation-4 - 使用参数安排从外部 XAML 加载的子 DynamicActivity

.net - 调试 WF 4 工作流服务时如何查看工作流变量

c# - 带有 C# 表达式的 XAMLX 工作流

silverlight-4.0 - WF4.0 与 Silverlight 4.0 集成