gpt4 book ai didi

wpf - 调试 WPF 事件、绑定(bind)

转载 作者:行者123 更新时间:2023-12-02 18:46:42 25 4
gpt4 key购买 nike

调试 WPF 事件或绑定(bind)时使用什么方法?

我尝试使用断点,但似乎我的 XAML 或代码后面有问题,它永远不会到达断点。

有没有办法查看当我单击 WPF 中的某些内容时,弹出或不弹出哪些事件消息,以了解出了什么问题?

最佳答案

在过去 3 年几乎全职构建 WPF 应用程序时,我收集了各种 react 性预防性解决方案,以确保< em>一切都正确地结合在一起。

注意: 我现在会给您一个快速总结,然后在早上(10 小时内)发回并附上代码示例/屏幕截​​图。

这些是我最有效的工具:

1) 创建一个转换器,在执行 ConvertConvertBack 时中断调试器。一种快速而有用的方法,可确保您获得所需的值。我第一次知道这个技巧是从Bea Stollnitz's blog post

DebugConverter.cs

public class DebugConverter : IValueConverter
{

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (Debugger.IsAttached)
Debugger.Break();

return Binding.DoNothing;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (Debugger.IsAttached)
Debugger.Break();

return Binding.DoNothing;
}

}

2) 创建一个拦截任何错误的 TraceListener。这与附加调试器时在 Visual Studio 输出窗口中看到的内容类似。使用此方法,当绑定(bind)操作期间抛出异常时,我可以让调试器中断。这比设置 PresentationTraceSources.TraceLevel 更好,因为它适用于整个应用程序,而不是每个绑定(bind)。

DataBindingErrorLogger.cs

public class DataBindingErrorLogger : DefaultTraceListener, IDisposable
{
private ILogger Logger;

public DataBindingErrorLogger(ILogger logger, SourceLevels level)
{
Logger = logger;

PresentationTraceSources.Refresh();
PresentationTraceSources.DataBindingSource.Listeners.Add(this);
PresentationTraceSources.DataBindingSource.Switch.Level = level;
}

public override void Write(string message)
{
}

public override void WriteLine(string message)
{
Logger.BindingError(message);

if (Debugger.IsAttached && message.Contains("Exception"))
Debugger.Break();
}

protected override void Dispose(bool disposing)
{
Flush();
Close();

PresentationTraceSources.DataBindingSource.Listeners.Remove(this);
}

}

使用

DataBindingErrorLogger = new DataBindingErrorLogger(Logger, SourceLevels.Warning);

在上面,ILoggerNLog日志作家。我有一个更复杂的 DefaultTraceListener 版本,它可以报告完整的堆栈跟踪并实际上抛出异常,但这足以让您开始(Jason Bock 有一个 article on this extended implementation 如果您想自己实现它) ,尽管您实际上需要代码才能使其工作)。

3) 使用Snoop WPF内省(introspection)工具可深入研究您的 View 并检查您的数据对象。使用 Snoop,您可以查看 View 的逻辑结构,并以交互方式更改值以测试不同的条件。

Snoop WPF

Snoop WPF 对于任何 WPF 应用程序的迭代时间都绝对重要。在其众多功能中,Delve 命令允许您深入查看 View / View 模型并交互式调整值。要深入研究属性,请右键单击打开上下文菜单并选择“深入”命令;要返回上一级(取消深入?),右上角有一个小按钮 ^。例如,尝试深入研究 DataContext 属性。

编辑:我不敢相信我刚刚注意到这一点,但是 Snoop WPF 窗口中有一个数据上下文选项卡。

DataContext Tab

4) 运行时检查 #DEBUG 中的 INotifyPropertyChanged 事件。由于数据绑定(bind)系统依赖于在属性更改时收到通知,因此通知正确的属性已更改对于您的理智非常重要。通过一点反射魔法,您可以在出现问题时Debug.Assert

PropertyChangedHelper.cs

public static class PropertyChangedHelper
{
#if DEBUG
public static Dictionary<Type, Dictionary<string, bool>> PropertyCache = new Dictionary<Type, Dictionary<string, bool>>();
#endif

[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, string propertyName)
{
sender.Notify(eventHandler, new PropertyChangedEventArgs(propertyName), true);
}

[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, string propertyName, bool validatePropertyName)
{
sender.Notify(eventHandler, new PropertyChangedEventArgs(propertyName), validatePropertyName);
}

[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, PropertyChangedEventArgs eventArgs)
{
sender.Notify(eventHandler, eventArgs, true);
}

[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, PropertyChangedEventArgs eventArgs, bool validatePropertyName)
{
#if DEBUG
if (validatePropertyName)
Debug.Assert(PropertyExists(sender as object, eventArgs.PropertyName), String.Format("Property: {0} does not exist on type: {1}", eventArgs.PropertyName, sender.GetType().ToString()));
#endif

// as the event handlers is a parameter is actually somewhat "thread safe"
// http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx
if (eventHandler != null)
eventHandler(sender, eventArgs);
}

#if DEBUG
[DebuggerStepThrough]
public static bool PropertyExists(object sender, string propertyName)
{
// we do not check validity of dynamic classes. it is possible, however since they're dynamic we couldn't cache them anyway.
if (sender is ICustomTypeDescriptor)
return true;

var senderType = sender.GetType();
if (!PropertyCache.ContainsKey(senderType))
PropertyCache.Add(senderType, new Dictionary<string,bool>());

lock (PropertyCache)
{
if (!(PropertyCache[senderType].ContainsKey(propertyName)))
{
var hasPropertyByName = (senderType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) != null);
PropertyCache[senderType].Add(propertyName, hasPropertyByName);
}
}

return PropertyCache[senderType][propertyName];
}
#endif

}

HTH,

关于wpf - 调试 WPF 事件、绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9609685/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com