2013-04-09 60 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這個。它可能有一些錯誤。但它給你一個想法你必須做的。