这应该是一个简单的问题,但我不明白。当我的自定义事件的某些属性发生更改(例如,通过在 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/