【问题标题】:How to debug binding in WPF如何在 WPF 中调试绑定
【发布时间】:2011-10-12 23:33:21
【问题描述】:

我有一个 VS2008、C# WPF、Excel 插件;在某些情况下,我的插件会抛出异常,如

A first chance exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll
A first chance exception of type 'System.NullReferenceException' occurred in PresentationFramework.dll

但我找不到异常的来源。我知道这是 b/c 数据绑定。但无法找出在哪里。每次我介入时,VS都会跟踪一个执行无错误的方法,然后抛出异常,但不知道哪行代码。

我已经为此苦苦挣扎了好几天,无法取得一点进展。 请帮忙。谢谢

编辑,太长了,不适合评论。所以我只是把xaml文件放在这里。引发异常的@xmal 文件。抛出异常的是DataGridComboBoxColumn

<UserControl x:Class="View.BasketView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit" >
    <UserControl.Resources>
        <sharedC:FunctionToHiddenVisibility x:Key="enumSRToVis"/>
        <sharedC:FunctionToHiddenVisibility x:Key="enumCSToVis"/>
        <Style x:Key="DataGridRowStyle"  TargetType="{x:Type dg:DataGridRow}">
            <Style.Triggers>
                <Trigger Property="AlternationIndex" Value="1" >
                    <Setter Property="Background" Value="Beige" />
                </Trigger>
            </Style.Triggers>
            <Setter Property="AllowDrop" Value="True" />
            <Setter Property="Margin" Value="0 2 0 2" />            
        </Style>
        <Style x:Key="DataGridStyle" TargetType="{x:Type dg:DataGrid}">
            <Setter Property="AlternationCount" Value="2" />
            <Setter Property="RowStyle" Value="{StaticResource DataGridRowStyle}" />
        </Style>
        <Style TargetType="{x:Type MenuItem}">
            <Style.Triggers>
                <Trigger Property="MenuItem.IsHighlighted" Value="True" >
                    <Setter Property="BorderBrush" >
                        <Setter.Value>
                            <SolidColorBrush Color="Gray"></SolidColorBrush>
                        </Setter.Value>
                    </Setter>
                    <Setter Property="BorderThickness" Value="1"/>
                </Trigger>
            </Style.Triggers>
        </Style>        
    </UserControl.Resources>
    <GroupBox>
        <GroupBox.Header>
            <TextBlock FontSize="14" FontFamily="Verdana" Text="{Binding Header,Mode=OneWay}"></TextBlock>
        </GroupBox.Header>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="33"></RowDefinition>
                <RowDefinition Height="*" ></RowDefinition>
                <RowDefinition Height="Auto"></RowDefinition>
            </Grid.RowDefinitions>

            <Border Margin="2 2 2 0">
                <Grid>

                    <Menu Background="Transparent">
                        <Menu.Resources>
                            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
                        </Menu.Resources>
                        <MenuItem IsEnabled="{Binding IsItemSelected}" Click="EditClick" ToolTip="Edit Relation(s)" Background="Transparent">
                            <MenuItem.Header>
                                <Image Width="16" Height="16" Source="{Binding EditImageFilePath}"/>
                            </MenuItem.Header>
                        </MenuItem>
                        <MenuItem IsEnabled="{Binding IsItemSelected}" Click="DeleteClick" ToolTip="Delete Relation(s)" Background="Transparent">
                            <MenuItem.Header>
                                <Image Width="16" Height="16" Source="{Binding DeleteImageFilePath}"/>
                            </MenuItem.Header>
                        </MenuItem>
                    </Menu>                             
                </Grid>
            </Border>

            <dg:DataGrid Grid.Row="1" x:Name="basketDG" Margin="5 0 5 0" Background="White"
                  AutoGenerateColumns="False" 
                  Style="{StaticResource DataGridStyle}"
                  SelectionMode="Extended"
                  GridLinesVisibility="None"
                  HeadersVisibility="Column" RowDetailsVisibilityMode="VisibleWhenSelected"
                  ItemsSource="{Binding BasketItems, Mode=OneWay}" CanUserAddRows="False" CanUserDeleteRows="False"
                  SelectionUnit="FullRow" SelectedItem="{Binding SelectedRelComplete}" 
                  VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
                  SelectionChanged="BasketDgSelectionChanged"                  
                  Drop="DataGridDrop" 
                  DragEnter="DataGridDragEnter" 
                  AllowDrop="True"
                 >

                <!-- Column definition -->
                <dg:DataGrid.Columns>
                    <dg:DataGridTextColumn IsReadOnly="True" Width="100" Header="Symbol" Binding="{Binding Name}" >
                        <dg:DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="TextWrapping" Value="Wrap" />
                            </Style>
                        </dg:DataGridTextColumn.ElementStyle>
                    </dg:DataGridTextColumn>              

                    <dg:DataGridTextColumn IsReadOnly="True" Width="*" Header="Symbol Description" Binding="{Binding Desc}" >
                        <dg:DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="TextTrimming" Value="WordEllipsis" />
                            </Style>
                        </dg:DataGridTextColumn.ElementStyle>
                    </dg:DataGridTextColumn>

                    <dg:DataGridComboBoxColumn Width="200" Header="Column" 
                        SelectedValueBinding="{Binding Path=RelParams.ColumnName, UpdateSourceTrigger=PropertyChanged}"
                        DisplayMemberPath="cName"
                        SelectedValuePath="cName">
                        <dg:DataGridComboBoxColumn.ElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter Property="ItemsSource" Value="{Binding RelInfo.Columns}" />
                            </Style>
                        </dg:DataGridComboBoxColumn.ElementStyle>
                        <dg:DataGridComboBoxColumn.EditingElementStyle>
                            <Style TargetType="ComboBox">
                                <Setter Property="ItemsSource" Value="{Binding RelInfo.Columns}" />
                            </Style>
                        </dg:DataGridComboBoxColumn.EditingElementStyle>
                    </dg:DataGridComboBoxColumn>

                </dg:DataGrid.Columns>               

            </dg:DataGrid>

            <Grid Grid.Row="2" Margin="0 5 0 0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" ></ColumnDefinition>
                    <ColumnDefinition Width="Auto" ></ColumnDefinition>
                    <ColumnDefinition Width="5" ></ColumnDefinition>
                    <ColumnDefinition Width="Auto" ></ColumnDefinition>
                </Grid.ColumnDefinitions>
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Grid.Column="0">
                    <Button Name="BtnSR" Visibility="{Binding SelectedFunction,  Converter={StaticResource enumSRToVis}}" IsEnabled="{Binding ItemsExist}" Margin="2" Click="ShowBasketSettings">Basket Settings</Button>
                </StackPanel>
                <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Grid.Column="0">
                    <Button Name="BtnCS" Visibility="{Binding SelectedFunction,  Converter={StaticResource enumCSToVis}}" IsEnabled="{Binding OnlyOneFutureItemExist}" Margin="2" Click="ShowCreateCurve">Curve Settings</Button>
                </StackPanel>
                <StackPanel Grid.Column="1">
                    <Button Width="50" Name ="BtnClear" ToolTip="Clear Basket" Margin="2" IsEnabled="{Binding ItemsExist}"
                            Click="BtnClear_Click">Clear</Button>
                </StackPanel>
                <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Grid.Column="3">                 
                    <Button Visibility ="{Binding ElementName=BtnSR, Path=Visibility}" 
                            ToolTip="Send Series Data to Table"
                            Name="SendToTable" Margin="2" Command="{Binding SendToTableCommand}" 
                            CommandParameter="{Binding ElementName=SendToTable}">Send to Table</Button>
                </StackPanel>
                <StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Grid.Column="3">
                    <Button Visibility="{Binding ElementName=BtnCS, Path=Visibility}" 
                            Name="CreateCurveSurface" Margin="2"                             
                            ToolTip="Send Curve Surface to Table"
                            IsEnabled="{Binding OnlyOneFutureItemExist}"
                            Click="CreateCurveSurfaceClick"
                    >Send to Table</Button>
                </StackPanel>
            </Grid>
        </Grid>
    </GroupBox>
</UserControl>

编辑:这里是堆栈跟踪

Name:NullReferenceException 消息:对象引用未设置为 对象的实例。目标:虚空 RestoreAttachedItemValue(System.Windows.DependencyObject, System.Windows.DependencyProperty)堆栈:在 Microsoft.Windows.Controls.DataGridRow.RestoreAttachedItemValue(DependencyObject objectWithProperty,DependencyProperty 属性)在 Microsoft.Windows.Controls.DataGridRow.SyncProperties(布尔 forcePrepareCells)在 Microsoft.Windows.Controls.DataGridRow.PrepareRow(对象项, DataGrid 拥有DataGrid) 在 Microsoft.Windows.Controls.DataGrid.PrepareContainerForItemOverride(DependencyObject 元素,对象项)在 System.Windows.Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.PrepareItemContainer(DependencyObject 容器,对象项目)在 System.Windows.Controls.ItemContainerGenerator.System.Windows.Controls.Primitives.IItemContainerGenerator.PrepareItemContainer(DependencyObject 容器)在 System.Windows.Controls.VirtualizingStackPanel.InsertContainer(Int32 childIndex,UIElement 容器,布尔 isRecycled)在 System.Windows.Controls.VirtualizingStackPanel.AddContainerFromGenerator(Int32 childIndex, UIElement child, Boolean newRealized) at System.Windows.Controls.VirtualizingStackPanel.BringIndexIntoView(Int32 指数)在 Microsoft.Windows.Controls.DataGrid.ScrollRowIntoView(对象项)
在 Microsoft.Windows.Controls.DataGrid.OnScrollIntoView(Object arg)
在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(委托 回调,对象参数,Int32 numArgs)在 MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(对象 源,委托方法,对象参数,Int32 numArgs,委托 catchHandler) 在 System.Windows.Threading.Dispatcher.WrappedInvoke(委托回调, 对象 args,Int32 numArgs,委托 catchHandler)在 System.Windows.Threading.DispatcherOperation.InvokeImpl() 在 System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(对象 状态)在 System.Threading.ExecutionContext.runTryCode(对象 用户数据)在 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode 代码,CleanupCode backoutCode,对象 userData)在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext、ContextCallback 回调、对象状态)在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext、ContextCallback 回调、对象状态、布尔值 ignoreSyncCtx) 在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext、ContextCallback 回调、对象状态)在 System.Windows.Threading.DispatcherOperation.Invoke() 在 System.Windows.Threading.Dispatcher.ProcessQueue() 在 System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd,Int32 味精,IntPtr wParam,IntPtr lParam,布尔值&处理)在 MS.Win32.HwndWrapper.WndProc(IntPtr hwnd,Int32 msg,IntPtr wParam, IntPtr lParam,布尔值&处理)在 MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) 在 System.Windows.Threading.ExceptionWrapper.InternalRealCall(委托 回调,对象参数,Int32 numArgs)在 MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(对象 源,委托方法,对象参数,Int32 numArgs,委托 catchHandler) 在 System.Windows.Threading.Dispatcher.WrappedInvoke(委托回调, 对象 args,Int32 numArgs,委托 catchHandler)在 System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority 优先级、TimeSpan 超时、委托方法、对象参数、Int32 numArgs) 在 MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 消息,IntPtr wParam,IntPtr lParam)在 MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg) 在 System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame 帧)在 System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame 框架)
在 System.Windows.Window.ShowHelper(Object booleanBox) 在 System.Windows.Window.Show() 在 System.Windows.Window.ShowDialog()

【问题讨论】:

    标签: c# wpf debugging excel add-in


    【解决方案1】:

    Wpf 捕获绑定异常,因此它们通常不会触发调试器中断。您可以使用 VS 中的 Debug\Exceptions 菜单命令让它们始终中断,单击 Find,输入您看到的异常(例如 System.InvalidOperationException)。单击确定,对话框应向下滚动到该异常。勾选“Thrown”列中的复选框,然后 VS 应该在调试时在抛出原始异常的任何代码行上中断。

    这将捕获该类型的所有异常 - 即使是您在 Try Catch 块中明确捕获的异常,所以请记住在完成调试时取消选中该框,否则您最终会想知道为什么 VS 会中断正在发生的异常抓到了。

    【讨论】:

    • 非常感谢你,fubaar。现在我明白了,但它仍然没有指向准确的代码行。即它说 Window.ShowDialog() 抛出异常,我知道窗口中的哪个部分,有一个内容(用户控件)抛出异常,但我无法找出 xaml 或 xaml.cs 或其 viewModel 中的哪一行导致例外
    • System.NullReferenceException 发生 Message="对象引用未设置为对象的实例。" Source="WPFToolkit" StackTrace:在 Microsoft.Windows.Controls.DataGridRow.RestoreAttachedItemValue(DependencyObject objectWithProperty, DependencyProperty property) 在 Microsoft.Windows.Controls.DataGridRow.SyncProperties(Boolean forcePrepareCells) 在 Microsoft.Windows.Controls.DataGridRow.PrepareRow(Object Microsoft.Windows.Controls.DataGrid.PrepareContainerForItemOverride(DependencyObject element, Object item) ....
    • 看起来 Wpf DataGrid 正在引发异常。它看起来不像可用的来源,所以您可能会试图缩小问题范围 - 我建议删除列/简化您的网格 Xaml 以尝试查明问题区域。您是否在网格模板中使用任何附加属性?您可以为该控件发布您的 Xaml 吗?
    【解决方案2】:

    我不确定您的问题的原因,但这里有一些关于如何调试 WPF 绑定的链接 -

    如何调试 WPF 绑定? http://www.zagstudio.com/blog/486 (WayBackLink)

    在 WPF 或 Silverlight 应用程序中调试数据绑定 http://blogs.msdn.com/b/wpfsldesigner/archive/2010/06/30/debugging-data-bindings-in-a-wpf-or-silverlight-application.aspx (WayBackLink)

    WPF 代码段 - 检测绑定错误
    http://www.switchonthecode.com/tutorials/wpf-snippet-detecting-binding-errors (WayBackLink)

    在 WPF 中调试数据绑定问题
    http://www.wpftutorial.net/DebugDataBinding.html

    【讨论】:

    • 嗯,尝试了转换器,PresentationTraceSources.TraceLevel=High,对我都不起作用。
    • 前 3 个链接现在已经失效,最后一个链接的解决方案不起作用,就像 @toosensitive 也指出的那样。这就是为什么你应该总是将重要的部分复制到你的答案中。
    • @Rico-E 感谢您指出 Rico;添加了指向回程机器的链接,因为它说没有什么在互联网上完全丢失:)
    • zagstudio 和 switchonthecode 的链接不再起作用。
    • @RedX 那些网站已关闭,请使用这些链接末尾附加的 WayBackLink。
    猜你喜欢
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    相关资源
    最近更新 更多