这应该是一个简单的,但我无法弄清楚。当我的自定义活动的某些属性发生更改时(例如,通过在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在设计器表面上不会改变。我错过了什么?
Will的答案是否正确。我在这里粘贴设计师* .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中包含活动并不能使解决方案显而易见,是吗?有点难以看到发生了什么,但它确实有效。干得好,威尔!
答案 0 :(得分:4)
您的Activity
包含在ModelItem
中,该here处理活动与设计界面之间的所有通知服务。
最初包含在设计器中时,ModelItem
会不检查您的Activity
以查看它是否提供了一些属性更改通知方法(INPC,自定义{{1 }}等等)或其他接口(即TypeDescriptor
,我有一个连接{{3}})。
所以,基本上,你不能做你想要在这里完成的事情。在Activity中,您无法通过包装ModelItem发回更改通知。无论如何,你真的不应该这样做。
在设计器中,状态更改应仅通过IDataErrorInfo
,因为它需要保持其状态与包装的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
当然,你不能只是把它复制一下。它可能有一些错误。但它让你知道你必须做什么。