FixedPage вызывает ArgumentNullException при слишком быстром наведении курсора - PullRequest
0 голосов
/ 21 марта 2020

Я сталкиваюсь с ситуацией, в которой WPF успешно создает элемент Image в одном из моих представлений, но, похоже, требуется секунда или две для правильной настройки логического родителя этого элемента. Если я наведу курсор мыши в этом временном окне, мое приложение вылетает из-за ArgumentNullException из LogicalTreeHelper.

Если я подожду секундочку или около того, все работает нормально и проблем нет. Но я вряд ли могу попросить своих пользователей сделать это.

Обратите внимание, что это происходит только тогда, когда мой UserControl размещен в FixedPage в FixedDocument, показанном DocumentViewer. Когда я использую тот же элемент управления в других контекстах (кроме FixedDocument и др.), Он работает без проблем.

Кто-нибудь знает что-нибудь об этом "окне" или что может быть причиной этого?

Это код в FixedPage.cs, который пытается получить родительский элемент моего элемента. Я добавил комментарии.

    internal int[] _CreateChildIndex(DependencyObject e)
    {
        ArrayList childPath = new ArrayList();
        while (e != this)
        { 
            // *** 'e' is an Image control, created by my view ***
            // *** This value 'parent' is NULL if I mouse over too quickly ***

            DependencyObject parent = LogicalTreeHelper.GetParent(e);
            int childIndex = -1;
            if (parent is FixedPage)
            {
                childIndex = ((FixedPage)parent).Children.IndexOf((UIElement)e);
            }
            else if (parent is Canvas)
            {
                childIndex = ((Canvas)parent).Children.IndexOf((UIElement)e);
            }
            else
            {
                // *** Because 'parent' is null, we end up here.  This call throws ***
                IEnumerable currentChildrens = LogicalTreeHelper.GetChildren(parent);

Вот код, который выбрасывает

public static IEnumerable GetChildren(DependencyObject current)
{
    if (current == null)
    {
        throw new ArgumentNullException("current"); 
    }

Это стек вызовов от наведения мыши. Здесь нет моего кода, кроме метода App.Run.

System.Windows.LogicalTreeHelper.GetChildren    C#
System.Windows.Documents.FixedPage._CreateChildIndex    C#
System.Windows.Documents.FixedTextView.GetTextPositionFromPoint C#
MS.Internal.Documents.TextViewBase.System.Windows.Documents.ITextView.GetTextPositionFromPoint  C#
MS.Internal.Documents.DocumentPageTextView.GetTextPositionFromPoint C#
MS.Internal.Documents.MultiPageTextView.GetTextPositionFromPoint    C#
MS.Internal.Documents.TextViewBase.System.Windows.Documents.ITextView.GetTextPositionFromPoint  C#
System.Windows.Documents.TextEditorMouse.IsPointWithinInteractiveArea   C#
System.Windows.Documents.TextEditorMouse.OnQueryCursor  C#
System.Windows.RoutedEventArgs.InvokeHandler    C#
System.Windows.EventRoute.InvokeHandlersImpl    C#
System.Windows.UIElement.RaiseEventImpl C#
System.Windows.UIElement.RaiseTrustedEvent  C#
System.Windows.Input.InputManager.ProcessStagingArea    C#
System.Windows.Input.MouseDevice.UpdateCursorPrivate    C#
System.Windows.Input.MouseDevice.PostProcessInput   C#
System.Windows.Input.InputManager.RaiseProcessInputEventHandlers    C#
System.Windows.Input.InputManager.ProcessStagingArea    C#
System.Windows.Input.InputProviderSite.ReportInput  C#
System.Windows.Interop.HwndMouseInputProvider.ReportInput   C#
System.Windows.Interop.HwndMouseInputProvider.FilterMessage C#
System.Windows.Interop.HwndSource.InputFilterMessage    C#
MS.Win32.HwndWrapper.WndProc    C#
MS.Win32.HwndSubclass.DispatcherCallbackOperation   C#
System.Windows.Threading.ExceptionWrapper.InternalRealCall  C#
System.Windows.Threading.ExceptionWrapper.TryCatchWhen  C#
System.Windows.Threading.Dispatcher.LegacyInvokeImpl    C#
MS.Win32.HwndSubclass.SubclassWndProc   C#
[Native to Managed Transition]  
UserCallWinProcCheckWow Unknown
DispatchMessageWorker   Unknown
[Managed to Native Transition]  
System.Windows.Threading.Dispatcher.PushFrameImpl   C#
System.Windows.Threading.Dispatcher.PushFrame   C#
System.Windows.Threading.Dispatcher.Run C#
System.Windows.Application.RunDispatcher    C#
System.Windows.Application.RunInternal  C#
System.Windows.Application.Run  C#
MyCompany.App.Main  Unknown   
[Native to Managed Transition]  
coreclr_t::execute_assembly C++
run_app_for_context C++
run_app C++
corehost_main   C++
execute_app C++
`anonymous namespace'::read_config_and_execute  C++
fx_muxer_t::handle_exec_host_command    C++
fx_muxer_t::execute C++
hostfxr_main_startupinfo    C++
exe_start   C++
wmain   C++
[Inline Frame] invoke_main  C++
__scrt_common_main_seh  C++
BaseThreadInitThunk()  Unknown
RtlUserThreadStart()   Unknown

Ниже приведена очень сокращенная версия моего представления (UserControl) с ItemsControl, который создает элемент Image

<UserControl
    x:Class="Core.Views.LayerView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:cv="clr-namespace:Core.View"
    >
    <Canvas>
        <ItemsControl ItemsSource="MyItems">
            <ItemsControl.Resources>
                <DataTemplate x:Key="PathOutputTemplate" DataType="{x:Type ShapeVm}">
                    <Path Stroke="Yellow" StrokeThickness="6" Data={Binding Geometry} />
                </DataTemplate>
                <DataTemplate x:Key="ImageOutputTemplate" DataType={x:Type ImageOutputVm}>
                    <Image Source="{Binding ImageSource}"/>
                </DataTemplate>
            </ItemsControl.Resources>
            <ItemsControl.ItemTemplateSelector>
              <cv:OutputTemplateSelector
                PathTemplate="{StaticResource PathOutputTemplate}"
                ImageTemplate="{StaticResource ImageOutputTemplate}"
                />
            </ItemsControl.ItemTemplateSelector>
        </ItemsControl>
    </Canvas>
</UserControl>
...