UWP与uwp中的FindAncestor等效

我有一个订单列表,当订单状态为Canceled时 ,我想要闪烁文本。 到目前为止,我的代码工作。 但是, 有时会抛出exception:

WinRT信息:无法解析TargetName lblOrderStatus

由于某种原因,可以找到lblOrderStatus 。 所以,我想使用“FindAncestor”,但UWP中不存在FindAncestor。 在uwp中是否有与FindAncestor等效的function?

这是我的代码:

 ... ... ...    ... ... ...                   

考虑到我见过的所有解决方案,我觉得使用ElementName绑定是UWP最简单的解决方法,没有RelativeSource AncestorType绑定选项。

假设你有一个将其DataContext设置为带有命令MyCommand的viewmodel的Page ,并且你希望列表中的每个项目在单击其按钮时执行它:

  ...         

我对此解决方案的初始问题是,您无法将DataTemplate作为资源提取出来,以便在多个屏幕(甚至是对话框)上使用它; thisPage可能不存在于每个位置,或者可能不适合将根元素命名为“thisPage”。

但是如果你使用一个约定,你在每个使用该DataTemplate的屏幕中包含一个令牌UI元素,并通过一致的名称引用它,它将起作用。 默认情况下,此元素的DataContext将是您的ViewModel(假设您的根元素也是如此)

  

…然后在您的独立资源XAML文件中,您可以像这样编写DataTemplate:

    

然后,在您使用该模板资源的每个页面/屏幕/对话框上,只需放入该Rectangle(或其他)的副本,一切都将在运行时正确绑定

这显然是一个黑客攻击解决方案,但在考虑了它之后,它首先感觉不再是使用WPF的AncestorType了(不得不确保你的祖先类型在所有地方始终保持一致)使用您的DataTemplate)。

在XAML中您可以尝试使用RelativeSource,它提供了一种根据运行时对象图中的相对关系指定绑定源的方法。 例如,使用TemplatedParent

 Height="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Parent.ActualHeight} 

要么

  

在代码中,您尝试使用VisualTreeHelper.GetParent方法。 https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.visualtreehelper.getparent

类似下面的内容,这里是一个实用function的例子

 internal static void FindChildren(List results, DependencyObject startNode) where T : DependencyObject { int count = VisualTreeHelper.GetChildrenCount(startNode); for (int i = 0; i < count; i++) { DependencyObject current = VisualTreeHelper.GetChild(startNode, i); if ((current.GetType()).Equals(typeof(T)) || (current.GetType().GetTypeInfo().IsSubclassOf(typeof(T)))) { T asType = (T)current; results.Add(asType); } FindChildren(results, current); } } 

以下示例显示了检查元素父级的代码

 ((StackPanel)LinePane.Parent).ActualWidth; 

此外,这是一篇很好的博客文章,展示了这个课程的实际应用。 http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html

我正在将一个应用程序从WPF转换为UWP并找到了这个post。 网络上似乎没有好的解决方案,所以这是我试图通过解决方法“解决”这个问题。

注意:以下是UWP中的UNTESTED(但在WPF中工作),因为我通过大型非编译端口,但理论上它应该工作…

1创建RelativeSourceBinding附加属性

该类有两个属性:AncestorType和Ancestor。 当AncestorType更改时,我们订阅FrameworkElement.Loaded(以处理父更改)并找到类型的可视父级并分配给Ancestor附加属性。

 public class RelativeSourceBinding { public static readonly DependencyProperty AncestorTypeProperty = DependencyProperty.RegisterAttached("AncestorType", typeof(Type), typeof(RelativeSourceBinding), new PropertyMetadata(default(Type), OnAncestorTypeChanged)); public static void SetAncestorType(DependencyObject element, Type value) { element.SetValue(AncestorTypeProperty, value); } public static Type GetAncestorType(DependencyObject element) { return (Type)element.GetValue(AncestorTypeProperty); } private static void OnAncestorTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((FrameworkElement)d).Loaded -= OnFrameworkElementLoaded; if (e.NewValue != null) { ((FrameworkElement)d).Loaded += OnFrameworkElementLoaded; OnFrameworkElementLoaded((FrameworkElement) d, null); } } private static void OnFrameworkElementLoaded(object sender, RoutedEventArgs e) { var ancestorType = GetAncestorType((FrameworkElement) sender); if (ancestorType != null) { var findAncestor = ((FrameworkElement) sender).FindVisualParent(ancestorType); RelativeSourceBinding.SetAncestor(((FrameworkElement)sender), findAncestor); } else { RelativeSourceBinding.SetAncestor(((FrameworkElement)sender), null); } } public static readonly DependencyProperty AncestorProperty = DependencyProperty.RegisterAttached("Ancestor", typeof(UIElement), typeof(RelativeSourceBinding), new PropertyMetadata(default(FrameworkElement))); public static void SetAncestor(DependencyObject element, UIElement value) { element.SetValue(AncestorProperty, value); } public static UIElement GetAncestor(DependencyObject element) { return (UIElement)element.GetValue(AncestorProperty); } } 

FindVisualParent是一个定义为的扩展方法

 public static UIElement FindVisualParent(this UIElement element, Type type) { UIElement parent = element; while (parent != null) { if (type.IsAssignableFrom(parent.GetType())) { return parent; } parent = VisualTreeHelper.GetParent(parent) as UIElement; } return null; } 

2在XAML中应用RelativeSourceBinding属性

WPF中的一些前缀xaml看起来像这样

  

和之后的xaml

  

它有点乱,但在你只有一个RelativeSource FindAncestor类型要查找的情况下,它应该可以工作。