2012-11-28 77 views
2

我有我的應用程序中的大部分Label對象綁定,以便它們可以從web服務中替換。WPF詞典綁定失敗是非常緩慢的

我將我的替換存儲在字典中。這些替換取決於爲應用程序加載的客戶端。

我遇到的問題是,大多數時候我不會替換標籤,並且綁定失敗會拋出非常慢的異常。

下面是一個例子:(正確地注意該代碼的功能,它只是緩慢,如果它不能找到匹配)

<Label Content="_Gender" 
     Helpers:CaptionHelper.PropertyName="Content" 
     Helpers:CaptionHelper.PropertyValue="{Binding Labels[Gender], 
                FallbackValue=_Gender}" 
     Target="{Binding ElementName=cbGender}" /> 

當結合試圖查找標貼[性別]我得到這個在我的輸出窗口:

System.Windows.Data Warning: 17 : Cannot get 'Item[]' value (type 'String') from 'Labels' (type 'Dictionary`2'). BindingExpression:Path=Labels[Gender]; DataItem='MyViewMV' 
     (HashCode=63776763); target element is 'Label' (Name=''); target property is 'PropertyValue'(type 'String') TargetInvocationException:'System.Reflection.TargetInvocationException: 
      Exception has been thrown by the target of an invocation. ---> System.Collections.Generic.KeyNotFoundException: 
      The given key was not present in the dictionary. 
    at System.Collections.Generic.Dictionary`2.get_Item(TKey key) 
    --- End of inner exception stack trace --- 
    at System.RuntimeMethodHandle._InvokeMethodFast(Params Truncated) 
    at System.Reflection.RuntimeMethodInfo.Invoke(Params Truncated) 
    at System.Reflection.RuntimeMethodInfo.Invoke(Params Truncated) 
    at MS.Internal.Data.PropertyPathWorker.GetValue(Params Truncated) 
    at MS.Internal.Data.PropertyPathWorker.RawValue(Params Truncated)' 

因爲我有很多這樣的,它走大約一整秒通過他們全部運行。

有沒有辦法讓字典查找失敗時綁定不會拋出異常?或者以某種方式失敗更快?

回答

3

如果可以選擇,我想你IDictionary實現改變一個返回null,轉而使用TargetNullValue(甚至是IDictionary<TKey, object>並返回DependencyProperty.UnsetValue如果你還在用FallbackValue):

public class PassthruDictionary<TKey, TValue> : IDictionary<TKey, TValue> 
{ 
    private Dictionary<TKey, TValue> instance; 

    // ... other stuff 

    public TValue this[TKey key] 
    { 
     get 
     { 
      TValue value; 
      if (instance.TryGetValue(key, out value)) 
      { 
       return value; 
      } 
      else 
      { 
       return default(TValue); 
      } 
     } 
     // ... more 
    } 
} 
+0

不知道這是否太老了澄清問題,但它在這裏:我似乎無法找到一種方法來返回DependecyProeprty.UnsetValue。假設我有一個'PassthruDictionary ',我該如何返回UnsetValue? (它爲我編譯但引發了運行時異常。) – Vaccano

1

是的,如果不在調試器中運行代碼,速度可以大大提高。其實在Visual Studio中stackteace的打印是到目前爲止最慢的部分是。如果你在沒有附加調試器的情況下運行你的應用程序,我相當確信性能的損失將不再明顯。

我有一個類似的問題,我們在庫內捕獲異常,即使你這樣做,VS會打印一條關於第一次機會異常被注入代碼的註釋,每次異常被捕獲(並處理) 。在啓動時,異常被觸發了大約50次,並且啓動應用程序的時間只有10秒,所有這些僅僅是因爲控制檯日誌記錄。一旦我運行沒有調試器的應用程序,它幾乎立即啓動。

所以也許試圖解決這個異常只是過早的優化。

+0

你是正確的。獨立運行並不慢。 – Vaccano

1

編輯:

其實,這一切都爲禁用VS輸出窗格中的輸出。它實際上並沒有加快速度。

ORIGINAL:

我也有類似的問題,但我想捕捉和記錄錯誤。但是,您可以使用以下解決方案來簡單地禁用將錯誤輸出到VS2010輸出窗口。該解決方案也有兩個部分,第一部分是一個簡單的類:

using System.Diagnostics; 

namespace DevBindingErrors 
{ 
    /// <summary> 
    /// Intercepts all binding error messages. Stops output appearing in VS2010 debug window. 
    /// </summary> 
    class BindingTraceListener: TraceListener 
    { 
     private string _messageType; 

     public override void Write(string message) 
     { 
      // Always happens in 2 stages: first stage writes "System.Windows.Data Error: 40 :" or similar. 
      _messageType = message; 
     } 

     public override void WriteLine(string message) 
     { 
      Debug.WriteLine(string.Format("{0}{1}", _messageType, message)); 
     } 
    } 
} 

第二部分是在App.xaml.cs:

using System.Diagnostics; 
using System.Windows; 

namespace DevBindingErrors 
{ 
    /// <summary> 
    /// Interaction logic for App.xaml 
    /// </summary> 
    public partial class App : Application 
    { 
     public App() 
     { 
      PresentationTraceSources.Refresh(); 
      PresentationTraceSources.DataBindingSource.Listeners.Add(new BindingTraceListener()); 
      PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Warning; 
     } 
    } 
} 

如果你想忽略所有綁定錯誤,只是評論出Debug.WriteLine(...)一行。 (儘管我不會推薦這個),這也會加快執行速度,而不會失去調試應用程序的能力。

這個解決方案的想法來自this page,它也有更多關於WPF中跟蹤源的細節。

+0

你可以不定義TRACE。 – user7116