2013-04-09 57 views
1

这应该是一个容易的,但我无法弄清楚。当我的自定义活动的某些属性发生更改(例如,通过在WF设计器中的属性网格中更改它)时,我想动态更新DisplayName。我在属性设置代码中这样做:在代码中更新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的更新代码,作为单独的答案来正确设置格式(不可作为注释)。此代码copmpiles并做的伎俩。

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

这个模型项目内的活动的包装并没有使解决方案变得明显,是吗?看看发生了什么有点难,但确实有效。伟大的工作,威尔!

+1

有关ModelItem的更多信息,请阅读此博文http://blogs.msdn.com/b/mwinkle/archive/2009/10/28/deep-dive-into-the-designer-data-model- modelitem-and-modelproperty.aspx它最初有点不一样,但是当你在WF设计师身上工作时,它变得更加清晰。 – Will 2013-04-10 14:52:59

+0

@威尔:伟大的博客文章,感谢您的指针。不知道我什么时候会处于我理解他写的所有内容的状态...... :) – Achim 2013-04-10 19:46:33

回答

2

你的Activity被包装在一个ModelItem中,其处理全部活动和设计表面之间的通知服务。

当最初包装设计中,该ModelItem确实检查你的Activity,看它是否提供了一些属性更改通知方法(INPC,定制TypeDescriptor等)或其它接口(即IDataErrorInfo,为此我有一个连接here)。

所以,基本上,你不能做你在这里试图完成的事情。在活动内,您无法通过包装模型项目发回更改通知。无论如何,你真的不应该这样做。

在设计,状态变化应该只有闯关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() + 
     ">"; 
} 

当然,你不能只是copypaste这个。它可能有一些错误。但它给你一个想法你必须做的。