虚拟化ListBox ContextMenu XamlParseException

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了虚拟化ListBox ContextMenu XamlParseException相关的知识,希望对你有一定的参考价值。

我有WPF(.NET 4.5)客户端应用程序,在虚拟化ListBox中有大量项目。每个ListBoxItem都有一些行动的ContextMenu

打开那个ContextMenu时,有些客户正在收到未处理的例外情况。在PC上安装了Windows 10和Windows Server 2012的PC几乎100%。

System.Windows.Markup.XamlParseException消息:

设置属性'System.Windows.Controls.HeaderedContentControl.Header'抛出异常。 ---> System.InvalidOperationException:指定的元素已经是另一个元素的逻辑子元素。首先断开它。

注意:我试图添加x:Shared="False" - 不是解决该问题

巨大的异常StackTrace:

System.Windows.Markup.XamlParseException: Set property 'System.Windows.Controls.HeaderedContentControl.Header' threw an exception. ---> System.InvalidOperationException: Specified element is already the logical child of another element. Disconnect it first.
at System.Windows.FrameworkElement.ChangeLogicalParent(DependencyObject newParent)
at System.Windows.FrameworkElement.AddLogicalChild(Object child)
at System.Windows.Controls.HeaderedItemsControl.OnHeaderChanged(Object oldHeader, Object newHeader)
at System.Windows.Controls.HeaderedItemsControl.OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)
--- End of inner exception stack trace ---
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlObjectWriter objectWriter)
at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List'1 affectedChildren, UncommonField'1 templatedNonFeChildrenField)
at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List'1 affectedChildren)
at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField'1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField'1 templateDataField, FrameworkElement container)
at System.Windows.FrameworkElement.ApplyTemplate()
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Control.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUniformOrAverageContainerSize, Double& computedUniformOrAverageContainerPixelSize, Boolean& computedAreContainersUniformlySized, IList& items, Object& item, IList& children, Int32& childIndex, Boolean& visualOrderChanged, Boolean& isHorizontal, Size& childConstraint, Rect& viewport, VirtualizationCacheLength& cacheSize, VirtualizationCacheLengthUnit& cacheUnit, Boolean& foundFirstItemInViewport, Double& firstItemInViewportOffset, Size& stackPixelSize, Size& stackPixelSizeInViewport, Size& stackPixelSizeInCacheBeforeViewport, Size& stackPixelSizeInCacheAfterViewport, Size& stackLogicalSize, Size& stackLogicalSizeInViewport, Size& stackLogicalSizeInCacheBeforeViewport, Size& stackLogicalSizeInCacheAfterViewport, Boolean& mustDisableVirtualization, Boolean isBeforeFirstItem, Boolean isAfterFirstItem, Boolean isAfterLastItem, Boolean skipActualMeasure, Boolean skipGeneration, Boolean& hasBringIntoViewContainerBeenMeasured, Boolean& hasVirtualizingChildren)
at System.Windows.Controls.VirtualizingStackPanel.MeasureOverrideImpl(Size constraint, Nullable'1& lastPageSafeOffset, List'1& previouslyMeasuredOffsets, Nullable'1& lastPagePixelSize, Boolean remeasure)
at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Control.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Border.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Control.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.Window.MeasureOverrideHelper(Size constraint)
at System.Windows.Window.MeasureOverride(Size availableSize)
at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
at System.Windows.UIElement.Measure(Size availableSize)
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.Resize(ICompositionTarget resizedCompositionTarget)
at System.Windows.Interop.HwndTarget.OnResize()
at System.Windows.Interop.HwndTarget.HandleMessage(WindowMessage msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Interop.HwndSource.HwndTargetFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

--Inner Exception:
System.InvalidOperationException: Specified element is already the logical child of another element. Disconnect it first.
at System.Windows.FrameworkElement.ChangeLogicalParent(DependencyObject newParent)
at System.Windows.FrameworkElement.AddLogicalChild(Object child)
at System.Windows.Controls.HeaderedItemsControl.OnHeaderChanged(Object oldHeader, Object newHeader)
at System.Windows.Controls.HeaderedItemsControl.OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember member, Object obj, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)

ContextMenu资源(在UserControl.Resources标签):

<ContextMenu x:Key="QuestionContextMenu">
    <MenuItem Command="{Binding AddChildCommand}"
              CommandParameter="{Binding Model}"
              Header="{StaticResource s_Question_Tooltip_AddChildAnswer}" />
    <MenuItem Command="{Binding RemoveCommand}"
              CommandParameter="{Binding Model}"
              Header="{StaticResource s_Remove}" />
</ContextMenu>

DataTemplate资源(在UserControl.Resources标签):

<DataTemplate x:Key="dt_Questions"
              DataType="secure:QuestionViewModel">
    <Grid x:Name="MainGrid"
          Width="{Binding ElementName=lvQuestions, Path=ActualWidth}"
          MinHeight="22"
          ContextMenu="{StaticResource QuestionContextMenu}"
          Margin="0 2 0 2">
        ...
    </Grid>
</DataTemplate>

Xaml的ListBox

<ListBox x:Name="lvQuestions"
         Grid.Row="1"
         Grid.Column="0"
         Grid.ColumnSpan="2"
         Padding="0 2 0 20"
         Panel.ZIndex="{Binding QuestionsZindex}"
         ItemTemplate="{StaticResource dt_Questions}"
         ItemsSource="{Binding QuestionsView, Mode=OneWay}"
         SelectedItem="{Binding SelectedQuestionViewModel, Mode=TwoWay}"
         SelectionMode="Single"
         Style="{StaticResource LeftListBox}"
         VirtualizingStackPanel.IsVirtualizing="True"
         VirtualizingStackPanel.ScrollUnit="Pixel"
         VirtualizingStackPanel.VirtualizationMode="Recycling" />

ListBox风格与模板:

<ItemsPanelTemplate x:Key="VirtualizingItemsPanelTemplate">
    <VirtualizingStackPanel />
</ItemsPanelTemplate>
<Style x:Key="LeftListBox"
        TargetType="{x:Type ListBox}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="Background" Value="{x:Null}" />
    <Setter Property="ItemsPanel" Value="{StaticResource VirtualizingItemsPanelTemplate}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBox}">
                <ScrollViewer Background="{TemplateBinding Background}"
                                            CanContentScroll="True"
                                            Style="{StaticResource LeftScrollViewerStyle}">
                    <ItemsPresenter Margin="{TemplateBinding Padding}" />
                </ScrollViewer>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ListBoxItem模板:

<Style TargetType="ListBoxItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的想法:我使用ContextMenu错误,或者它是.NET 4.5中ScrollUnit="Pixel"的问题。

PS:我花了很多时间来确定问题来源是ContextMenu。我试图以某种方式重新制作我的XAML标记以解决该问题......问题仍然出现。我不想禁用虚拟化或制作我自己的ContextMenu控件。我想找到解决该问题的方法。

答案

找到答案:

异常的来源不是qazxsw poi,它是qazxsw poi与qazxsw poi属性设置为ContextMenu到我的本地化值。这个价值资源是MenuItem,而不是Header

是:

StaticResource

固定:

TextBlock

以上是关于虚拟化ListBox ContextMenu XamlParseException的主要内容,如果未能解决你的问题,请参考以下文章

如何在wpf用listbox中添加右键菜单

列表框 contextMenu 子项单击

WPF如何去掉ContextMenu的显示和隐藏动画

当我右键单击一个项目时,如何防止 ListBox 选择它?

带有包装和虚拟化的ListBox

WPF ListBox/ListView/DataGrid 列表滚动与虚拟化