我定义了以下XAML。
<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>
如果我使用来自“mainGrid”的VisualTreeHelper.GetParent走向可视树,我最终得到System.Windows.Controls.Primitives.PopupRoot,但永远不会获得Popup本身。任何人都有关于为什么会这样做以及我能做些什么的理论?我需要Popup而不是PopupRoot。
TIA。
答案 0 :(得分:16)
弹出窗口中的内容会添加到不同的可视树中,其父级是PopupRoot,但您可以使用逻辑树助手来获取此代码段的弹出窗口:
LogicalTreeHelper.GetParent()
来自MSDN:
向Popup控件添加内容时,Popup控件将成为内容的逻辑父级。同样,Popup内容被认为是Popup的逻辑子代。子内容未添加到包含Popup控件的可视树中。相反,当IsOpen属性设置为true时,子内容将在单独的窗口中呈现,该窗口具有自己的可视树。
++
答案 1 :(得分:4)
尝试遍历逻辑树而不是Visual树
LogicalTreeHelper.GetParent()
答案 2 :(得分:4)
LogicalTreeHelper
无法访问Popup,最好的方法是尝试使用“PopupRoot”命名与GetType().Name
进行比较。
答案 3 :(得分:3)
使用此:
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;
}
答案 4 :(得分:2)
基于this answer以及此处提供的答案(感谢Wouter的评论),我终于想出了这个:
using System.Windows.Media;
using System.Windows.Media.Media3D;
public static class FamilyHelper
{
public static T FindAncestor<T>(this DependencyObject dObj) where T : DependencyObject
{
while (true)
{
if (dObj == null) return null;
var parent = VisualTreeHelper.GetParent(dObj as Visual ?? new UIElement())
?? VisualTreeHelper.GetParent(dObj as Visual3D ?? new UIElement())
?? LogicalTreeHelper.GetParent(dObj);
if (parent is T) return (T) parentT;
dObj = parent;
}
}
}
永远不会出错,适用于所有类型的控件,例如
var element = sender as UIElement;
var parentWindow = element.FindAncestor<Window>();
答案 5 :(得分: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
}
}