【问题标题】:Updating DisplayName in code, does not show up in designer?在代码中更新 DisplayName,没有显示在设计器中?
【发布时间】:2013-04-09 19:11:28
【问题描述】:

这应该很容易,但我想不通。当我的自定义活动的某些属性发生变化时(例如,通过在 WF 设计器的属性网格中更改它),我想动态更新 DisplayName。我在属性设置器代码中这样做:

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 +">");
    }

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

【问题讨论】:

  • 有关 ModelItem 的更多信息,请阅读此博客文章 blogs.msdn.com/b/mwinkle/archive/2009/10/28/… 最初有点混乱,但随着您与 WF 设计师合作,它会变得更加清晰。
  • @Will:很棒的博文,感谢您的指点。不知道什么时候我会处于我理解他所写的一切的状态...... :)

标签: workflow-foundation-4 activitydesigner


【解决方案1】:

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

当最初包装在设计器中时,ModelItem 确实检查您的 Activity 以查看它是否提供了一些属性更改通知方法(INPC、自定义 TypeDescriptor 等)或其他接口(即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!";

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

相反,将这样的代码移动到设计器中!

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() + 
        ">";
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-07
    • 2017-05-19
    • 2019-03-04
    • 2021-07-31
    相关资源
    最近更新 更多