2010-09-25 9 views
12

Ho definito il seguente XAML.wPF VisualTreeHelper.GetParent restituisce una classe errata?

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

Se cammino fino ad albero visuale utilizzando VisualTreeHelper.GetParent da "mainGrid", alla fine ho capito System.Windows.Controls.Primitives.PopupRoot, ma mai la Popup stesso. Qualcuno con una teoria sul perché questo è e cosa posso fare al riguardo? Ho creato Popup e non PopupRoot.

TIA.

+0

Funziona se si utilizza 'LogicalTreeHelper.GetParent()'? –

risposta

16

il contenuto di una pop-up si aggiunge ad un altro albero visiva con un genitore che è il PopupRoot ma è possibile utilizzare la struttura di supporto logico per ottenere il popup con questo frammento:

LogicalTreeHelper.GetParent() 

Da MSDN:

Quando aggiungi contenuto a un controllo Popup, il controllo Popup diventa il genitore logico del contenuto. Allo stesso modo, il contenuto di Popup è considerato il figlio logico del Popup. Il contenuto secondario non viene aggiunto all'albero visivo che contiene il controllo Popup. Invece, il contenuto secondario viene visualizzato in una finestra separata con il proprio albero visivo quando la proprietà IsOpen è impostata su true.

++

+0

Grazie per tutti i commenti ragazzi. –

3

provare a camminare l'albero logico e non l'albero visuale

LogicalTreeHelper.GetParent() 
4

LogicalTreeHelper è in grado di raggiungere il Popup e il migliore si poteva fare è provare a utilizzare il nome del "PopupRoot" da confrontare con GetType().Name.

+0

questo esattamente quello che ho usato. – Artiom

+0

L'albero logico contiene Popup, basta avviarlo ricorsivamente. È qui. –

+1

Nel mio caso, il genitore logico del mio genitore logico è nullo. Nel mio caso, devo attraversare l'albero visivo fino a PopupRoot e poi è Logical Parent è il Popup. Purtroppo non riesco a cercare un genitore di tipo PopupRoot poiché PopupRoot è interno al suo pacchetto. Inoltre, non esiste un metodo esistente per ottenere la radice visiva, che in questo caso sarebbe PopupRoot. Non voglio scrivere un metodo di estensione per ottenere il Visual Root solo per una singola situazione. Quindi attualmente non ho una soluzione. – Skychan

3

Utilizzare questa:

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

Sulla base this answer e le risposte qui presentati, ho finalmente si avvicinò con questo:

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

che non va mai storto e funziona per a ll tipi di controlli.

+0

Ciò genera un'eccezione quando dependencyObject non è Visual o Visual3D. Dovresti sostituire il ?? la linea con corrente è Visual || la corrente è Visual3D? VisualTreeHelper.GetParent (corrente): LogicalTreeHelper.GetParent (corrente); – Wouter

+0

@Wouter: Scusa ma non ha senso. Il metodo 'VisualTreeHelper.GetParent' genera un'eccezione solo quando' dependencyObject' è nullo. Vedere [here] (https://docs.microsoft.com/en-us/previous-versions/windows/apps/ms608747 (v = vs.105)) –

+0

Il collegamento sembra interrotto. Ma potresti voler controllare qualsiasi elemento di contenuto come ad esempio un elemento di testo. – Wouter

Problemi correlati