我的应用程序绑定了大多数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)'
由于我有很多这些,所以需要大约一整秒才能完成所有这些。
当字典查找失败时,有没有办法使绑定不抛出异常?或者以某种方式更快失败?
答案 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中跟踪源的更多详细信息。