2010-09-25 10 views
12

Mam następujące definicje XAML.wPF VisualTreeHelper.GetParent zwraca niewłaściwą klasę?

<Popup x:Class="EMS.Controls.Dictionary.MapTip" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    PopupAnimation="Slide" 
    AllowsTransparency="True" Placement="Mouse"  
     x:Name="root"     
     > 

    <Popup.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="../Resources/Styles.xaml"/> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Popup.Resources> 
    <Viewbox x:Name="viewBox" IsHitTestVisible="True"> 
     <Grid Background="Transparent" Name="mainGrid"> 

     </Grid> 
    </Viewbox> 
</Popup> 

Jeżeli idę w górę drzewa wizualnej przy użyciu VisualTreeHelper.GetParent z „mainGrid” I w końcu dostać System.Windows.Controls.Primitives.PopupRoot, ale nigdy się sam podręcznym. Ktoś z teorią, dlaczego tak jest i co mogę z tym zrobić? Jestem Popup, a nie PopupRoot.

TIA.

+0

Czy to działa, jeśli zamiast tego używasz 'LogicalTreeHelper.GetParent()'? –

Odpowiedz

16

Zawartość w popup jest dodawana do innego drzewa wizualnej z rodzicem, który jest PopupRoot ale można użyć logicznego drzewo pomocnika, aby uzyskać popup z tego fragmentu:

LogicalTreeHelper.GetParent() 

Od MSDN:

Po dodaniu treści do formantu typu Popup kontrolka podręczna staje się logicznym elementem nadrzędnym dla treści. Podobnie, treść Popup jest uważana za logiczne dziecko Popup. Zawartość podrzędna nie jest dodawana do drzewa wizualnego zawierającego kontrolkę Popup. Zamiast tego treść podrzędna jest renderowana w osobnym oknie, które ma własne drzewo wizualne, gdy właściwość IsOpen ma wartość true.

++

+0

Dzięki za wszystkie komentarze. –

3

Spróbuj chodzenia Logical drzewa, a nie wizualne drzewa

LogicalTreeHelper.GetParent() 
4

LogicalTreeHelper nie jest w stanie dotrzeć do Popup także najlepszy mogła zrobić, to spróbuj użyć nazwie The "PopupRoot" porównać do GetType().Name.

+0

dokładnie to, czego użyłem. – Artiom

+0

Drzewo logiczne zawiera Popup, po prostu rekurencyjnie go przechodź. Jest tam. –

+1

W moim przypadku logiczny element nadrzędny mojego logicznego elementu nadrzędnego ma wartość null. W moim przypadku muszę przejść drzewo wizualne aż do PopupRoot, a następnie Logical Parent to Popup. Niestety nie mogę wyszukać rodzica typu PopupRoot, ponieważ PopupRoot jest wewnętrznym pakietem. Ponadto nie istnieje żadna metoda uzyskiwania Visual Root, który w tym przypadku byłby PopupRoot. Nie chcę pisać metody rozszerzenia, aby uzyskać Visual Root tylko dla jednej sytuacji. Więc obecnie nie mam rozwiązania. – Skychan

3

Użyj tego:

Popup oPopup = VisualHelper.GetLogicalParent<Popup>(oThumb); 

...

public static T GetLogicalParent<T>(DependencyObject p_oElement) 
    where T : DependencyObject 
{ 
    DependencyObject oParent = p_oElement; 
    Type oTargetType = typeof(T); 
    do 
    { 
     oParent = LogicalTreeHelper.GetParent(oParent); 
    } 
    while (
     !(
      oParent == null 
      || oParent.GetType() == oTargetType 
      || oParent.GetType().IsSubclassOf(oTargetType) 
     ) 
    ); 

    return oParent as T; 
} 
1
private void btnRemove_Click(object sender, RoutedEventArgs e) 
    { 

     CloseScatterViewItem((SurfaceButton)sender); 
    } 

    private void CloseScatterViewItem(SurfaceButton button) 
    { 
     DependencyObject parent = button; 
     while ((parent as ScatterViewItem) == null) 
     { 

      // Get the next parent. 
      parent = LogicalTreeHelper.GetParent(parent) != null ? LogicalTreeHelper.GetParent(parent) : VisualTreeHelper.GetParent(parent); 
      ScatterViewItem item = parent as ScatterViewItem; 
      if (item != null) 
      { 
       DependencyObject scatterView = item; 
       while ((scatterView as ScatterView) == null) 
       { 
        scatterView = LogicalTreeHelper.GetParent(scatterView) != null ? LogicalTreeHelper.GetParent(scatterView) : VisualTreeHelper.GetParent(scatterView); 
        ScatterView FoundSV = scatterView as ScatterView; 
        if (FoundSV != null) 
        { 
         //FoundSV.Items.Remove(item); 
         FadeOutAndRemove(FoundSV, item); 
         return; 
        } 
       } 
      } 
     } 

    } 
    public static void FadeOutAndRemove(ScatterView sv, ScatterViewItem svi) 
    { 
     try 
     { 
      svi.Opacity = 1.0; 

      var a = new DoubleAnimation 
      { 
       From = 1.0, 
       To = 0.0, 
       FillBehavior = FillBehavior.Stop, 
       BeginTime = TimeSpan.FromSeconds(0), 
       Duration = new Duration(TimeSpan.FromSeconds(0.5)) 
      }; 

      var storyboard = new Storyboard(); 
      storyboard.Children.Add(a); 

      Storyboard.SetTarget(a, svi); 
      Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty)); 

      storyboard.Completed += delegate 
      { 
       svi.Visibility = Visibility.Hidden; 
       sv.Items.Remove(svi); 
       svi.Content = null; 
       svi = null; 
      }; 

      storyboard.Begin(); 
     } 
     catch (Exception ex) 
     { 
      //Handle error 

     } 
    } 
2

podstawie this answer i odpowiedzi przedstawione tutaj, w końcu wpadł na to:

public static class FindMyParentHelper<T> where T : DependencyObject 
{ 
    public static T FindAncestor(DependencyObject dependencyObject) 
    { 
     while (true) 
     { 
      if (dependencyObject == null) return null; 

      var parent = VisualTreeHelper.GetParent(dependencyObject) ?? 
         LogicalTreeHelper.GetParent(dependencyObject); 

      var parentT = parent as T; 
      if (parentT != null) return parentT; 

      dependencyObject = parent; 
     } 
    } 
} 

która nigdy nie idzie źle i działa na Wszystkie rodzaje kontroli.

+0

Spowoduje to zgłoszenie wyjątku, gdy obiekt dependencyObject nie jest programem Visual lub Visual3D. Powinieneś wymienić? linia z bieżącym jest Visual || obecny jest Visual3D? VisualTreeHelper.GetParent (current): LogicalTreeHelper.GetParent (current); – Wouter

+0

@Wouter: Przepraszam, ale to nonsens. Metoda 'VisualTreeHelper.GetParent' zgłasza wyjątek tylko wtedy, gdy' dependencyObject' ma wartość null. Zobacz [tutaj] (https://docs.microsoft.com/en-us/previous-versions/windows/apps/ms608747 (v = vs.105)). –

+0

Link wydaje się być uszkodzony. Ale możesz chcieć sprawdzić dowolne treści, takie jak na przykład tekstelement. – Wouter

Powiązane problemy