WPF字典绑定失败非常慢

时间:2012-11-28 16:45:41

标签: c# .net wpf xaml

我的应用程序绑定了大多数Label个对象,以便可以从Web服务中替换它们。

我将替换词存储在词典中。替换项根据为应用程序加载的客户端而有所不同。

我遇到的问题是大多数时候我没有替换标签,绑定失败会导致异常非常慢。

以下是一个示例:(请注意,此代码正常运行,如果无法找到匹配项,则速度很慢。)

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

当绑定尝试查找Lables [Gender]时,我会在输出窗口中看到它:

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 个答案:

答案 0 :(得分:3)

如果您可以选择,我会将您的IDictionary实施更改为返回null的实施,而是使用TargetNullValue(或甚至是IDictionary<TKey, object>并返回{{ 1}}如果您仍然使用DependencyProperty.UnsetValue):

FallbackValue

答案 1 :(得分:1)

是的,如果您不在调试器中运行代码,速度可以大大提高。实际上,在Visual Studio中打印堆栈是到目前为止最慢的部分。如果您在没有附加调试器的情况下运行应用程序,我很确定性能损失将不再是显而易见的。

我有一个类似的问题,我们在库中捕获异常,即使你这样做,VS也会打印一个关于每次捕获(和处理)异常时代码中捕获的第一次机会异常的注释。该异常在启动时被触发了大约50次,并且启动所需的应用程序只需10秒,而这一切只是因为控制台日志记录。一旦我在没有调试器的情况下运行应用程序,它几乎立即启动。

因此,尝试解决该异常只是过早优化。

答案 2 :(得分: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中跟踪源的更多详细信息。