2016-07-12 8 views
5

Manchmal klicken Sie mit der rechten Maustaste auf treeviewitem Ergebnisse unbehandelt InvalidOperationException. Im Code dahinter wähle ich die rechte angeklickte Zeile:Warum klicken Sie auf Baumwürfe "System.Windows.Documents.Run" ist keine Visual oder Visual3D 'InvalidOperationException?

static TreeViewItem VisualUpwardSearch(DependencyObject source) 
    { 
     while (source != null && !(source is TreeViewItem)) 
      source = VisualTreeHelper.GetParent(source); 

     return source as TreeViewItem; 
    } 

    private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) 
    { 
      TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject); 

      if (treeViewItem != null) 
      { 
       treeViewItem.Focus(); 
       e.Handled = true; 
      } 
    } 

Laut StackTrace oben ist die Ursache des Problems.

XAML:

<UserControl.Resources> 
    <HierarchicalDataTemplate ItemsSource="{Binding ClassesItemsSource}" DataType="{x:Type pnls:FavoriteObjectTableViewModel}"> 
     <StackPanel Orientation="Horizontal"> 
      <Image Source="{Binding Converter={StaticResource nameToBitmapSource}}" DataContext="{Binding Bitmap}" /> 
      <Label Content="{Binding TableName}"/> 
     </StackPanel> 
    </HierarchicalDataTemplate> 
    <DataTemplate DataType="{x:Type pnls:FavoriteObjectClassViewModel}"> 
     <StackPanel Orientation="Horizontal"> 
      <Image Source="{Binding Bitmap, Converter={StaticResource UriToCachedImageConverter}}"/> 
      <Label Content="{Binding ClassName}"/> 
     </StackPanel> 
    </DataTemplate> 
</UserControl.Resources> 

<TreeView Name="Insert_ObjectTreeIE" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding TablesItemsSource}"> 
     <TreeView.ItemContainerStyle> 
      <Style TargetType="TreeViewItem"> 
       <Setter Property="IsSelected" Value="{Binding IsSelected}" /> 
       <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> 
       <EventSetter Event="PreviewMouseRightButtonDown" Handler="OnPreviewMouseRightButtonDown"></EventSetter> 
       <EventSetter Event="MouseDoubleClick" Handler="OnMouseDoubleClick" /> 
      </Style> 
     </TreeView.ItemContainerStyle> 
</TreeView> 

Stacktrace:

e.StackTrace " at MS.Internal.Media.VisualTreeUtils.AsVisual(DependencyObject element, Visual& visual, Visual3D& visual3D)\r\n 
at MS.Internal.Media.VisualTreeUtils.AsNonNullVisual(DependencyObject element, Visual& visual, Visual3D& visual3D)\r\n 
at System.Windows.Media.VisualTreeHelper.GetParent(DependencyObject reference)\r\n 
at Tekla.Nis.Application.Shared.UI.Panels.FavoriteObjectsView.VisualUpwardSearch(DependencyObject source) in c:\\XXX\\161wpf\\src\\SharedAppFeature\\Panels\\FavoriteObjectsView.xaml.cs:line 45\r\n 
at Application.Shared.UI.Panels.FavoriteObjectsView.OnPreviewMouseRightButtonDown(Object sender, MouseButtonEventArgs e) in c:\\XXX\\161wpf\\src\\NisSharedAppFeature\\Panels\\FavoriteObjectsView.xaml.cs:line 52\r\n 
at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)\r\n 
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)\r\n 
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)\r\n 
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)\r\n 
at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)\r\n 
at System.Windows.UIElement.OnPreviewMouseDownThunk(Object sender, MouseButtonEventArgs e)\r\n 
at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)\r\n 
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)\r\n at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)\r\n 
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)\r\n 
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)\r\n at System.Windows.ContentElement.RaiseTrustedEvent(RoutedEventArgs args)\r\n 
at System.Windows.Input.InputManager.ProcessStagingArea()\r\n 
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)\r\n 
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)\r\n 
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)\r\n 
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)\r\n 
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)\r\n 
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)\r\n at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)\r\n 
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)\r\n 
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)\r\n 
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)\r\n 
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)\r\n 
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)\r\n 
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)\r\n 
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)\r\n 
at System.Windows.Application.RunDispatcher(Object ignore)\r\n 
at System.Windows.Application.RunInternal(Window window)\r\n 
at System.Windows.Application.Run(Window window)\r\n 
at System.Windows.Application.Run()\r\n at "my application start location" 

kann ich dies manchmal nur reproduzieren. Mein Kollege sagte, Linksklick auf Punkt 1 und Rechtsklick auf Punkt 2 erzeugt dies jedes Mal in bestimmten Baum.

+0

Ein 'Run' ist kein Visual und müsste separat gehandhabt werden. Funktioniert 'VisualUpwardSearch (e.Quelle als DependencyObject)' 'bereits für Sie? Außerdem: Um den Klick zu reproduzieren muss auf dem Label nicht das Bild passieren! –

+0

Ich klicke auf Textblock, nicht auf Bild, aber jetzt klicke ich seit Minuten und kann es nicht reproduzieren. also weiß ich nicht, ob diese Änderung einen Unterschied macht. –

+0

plus ändern es zu e.Quelle Ergebnisse der Artikel Eltern ausgewählt werden –

Antwort

6

Die Probleme wiedergibt, wenn Sie irgendwo in den Text der Bezeichnung klicken. In diesem Fall wird die e.OriginalSource ein Run Objekt sein, das ein Teil der inneren Zusammensetzung der Label oder TextBox ist. Das Run Element erbt nicht von einer Visual Klasse, also nicht ein Teil der visuellen Struktur, in diesem Fall kann die VisualTreeHelper.GetParent(source);InvalidOperationException werfen.

Die einfachste Lösung wird jede Textsteuerung (Label in Ihrem Fall) machen zu IsHitTestVisible="False", wird dies diese Kontrollen von Treffertestlogik ausschließen, was bedeutet, dass es nie die e.OriginalSource ein Ereignis sein, Eltern ist es stattdessen sein abgeholt und höchstwahrscheinlich das Elternteil wird ein Visual Element sein.

+0

danke! gründliche Tests zeigen, ob das Problem behoben wurde. für mich war es fast unmöglich zu reproduzieren. In 1h des Klickens habe ich geschafft, die Ausnahme 2mal zu bekommen. +1 zur Erklärung. Kannst du mir etwas über "wahrscheinlichsten Teil" erzählen? das kann also auch passieren, wenn ich IsHitTestVisible = "False" setze? –

+0

also zusätzliche Prüfung "wenn (Quelle ist Visual)" könnte hinzugefügt werden, nur um auf der sicheren Seite zu sein? –

+0

Nein, kümmern Sie sich nicht um die Überprüfung, es kann zukünftige Probleme maskieren, ich erwähnte, dass es "höchstwahrscheinlich ein Visual" sein wird, da es Fälle geben kann, wenn Sie Ihren Vorlagen andere Textelemente hinzufügen, ohne IsHitTestVisible auf false zu setzen. In Ihrem Fall ist es zu 100% sicher. Sie können IsHitTestVisible nur auf das root StackPanel Ihrer Vorlagen setzen, um das Problem mit anderen Textelementen in der Vorlage zu vermeiden. –