2010-09-25 14 views
12

Tengo definido el siguiente XAML.wPF VisualTreeHelper.GetParent devuelve la clase incorrecta?

<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> 

Si camino hasta el árbol visual utilizando VisualTreeHelper.GetParent de "mainGrid", que finalmente consigo System.Windows.Controls.Primitives.PopupRoot, pero nunca conseguir la ventana emergente en sí. ¿Alguien con una teoría sobre por qué esto es y qué puedo hacer al respecto? Necesité Popup y no PopupRoot.

TIA.

+0

¿Funciona si utiliza 'LogicalTreeHelper.GetParent()' en su lugar? –

Respuesta

16

Se añade el contenido en una ventana emergente con un árbol visual diferente con un padre que es el PopupRoot pero se puede utilizar el ayudante árbol lógico para conseguir la ventana emergente con este fragmento:

LogicalTreeHelper.GetParent() 

de MSDN:

Cuando agrega contenido a un control emergente, el control emergente se convierte en el padre lógico del contenido. Del mismo modo, se considera que el contenido emergente es el elemento lógico del elemento emergente. El contenido secundario no se agrega al árbol visual que contiene el control emergente. En cambio, el contenido secundario se representa en una ventana separada que tiene su propio árbol visual cuando la propiedad IsOpen se establece en verdadero.

++

+0

Gracias por todos los comentarios chicos. –

3

Intenta recorrer el árbol lógico y no el árbol visual

LogicalTreeHelper.GetParent() 
4

LogicalTreeHelper es incapaz de alcanzar el emergente así la mejor opción podría hacer es tratar de usar el nombre del "PopupRoot" para comparar a GetType().Name.

+0

esto es exactamente lo que usé. – Artiom

+0

El árbol lógico no contiene Popup, simplemente lo recorre recursivamente. Está ahí. –

+1

En mi caso, el elemento primario lógico de mi elemento primario lógico es nulo. En mi caso, tengo que atravesar el árbol visual hasta PopupRoot y luego es Logical Parent el Popup. Desafortunadamente no puedo buscar un padre de tipo PopupRoot porque PopupRoot es interno a su paquete. Además, no existe un método existente para obtener Visual Root, que en este caso sería PopupRoot. No quiero escribir un método de extensión para obtener la raíz visual solo para una sola situación. Entonces, actualmente no tengo una solución. – Skychan

3

Utilice esta:

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

Basado en this answer y las respuestas presentadas aquí, por fin se le ocurrió esto:

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; 
     } 
    } 
} 

que nunca sale mal y funciona para ll tipos de controles.

+0

Esto arroja una excepción cuando dependencyObject no es un Visual o Visual 3D. Deberías reemplazar el ?? la línea con la corriente es Visual || la corriente es Visual3D? VisualTreeHelper.GetParent (actual): LogicalTreeHelper.GetParent (actual); – Wouter

+0

@Wouter: Lo siento pero eso no tiene sentido. El método 'VisualTreeHelper.GetParent' lanza una excepción solo cuando' dependencyObject' es nulo. Ver [aquí] (https://docs.microsoft.com/en-us/previous-versions/windows/apps/ms608747 (v = vs.105)) –

+0

El enlace parece estar roto. Pero es posible que desee comprobar si hay contenido como, por ejemplo, un elemento de texto. – Wouter

Cuestiones relacionadas