2

我绑定了我的应用程序中的大多数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)'

因为我有很多这样的东西,所以要花整整一秒钟的时间来浏览它们。

当字典查找失败时,有没有办法使绑定不抛出异常?或者以某种方式更快地失败?

4

3 回答 3

3

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

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
    }
}
于 2012-11-28T17:29:43.517 回答
1

是的,如果您不在调试器中运行代码,则可以显着提高速度。实际上,Visual Studio 中 stackteace 的打印是迄今为止最慢的部分。如果您在没有附加调试器的情况下运行应用程序,我很确定性能损失将不再明显。

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

所以也许试图解决这个异常只是过早的优化。

于 2012-11-28T16:53:12.017 回答
1

编辑:

实际上,所有这一切都是在 VS 输出窗格中禁用输出。它实际上并没有加快速度。

原来的:

我有一个类似的问题,但我想捕捉并记录错误。但是,您可以使用以下解决方案简单地禁用将错误输出到 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(...)行。(虽然我不会真的推荐这个)这也将加快执行速度,而不会失去调试应用程序的能力。

这个解决方案的想法来自这个页面,它也有更多关于 WPF 中跟踪源的详细信息。

于 2012-11-28T17:20:41.050 回答