Sam*_*Sam 10 c# win-universal-app uwp windows-10-universal uwp-xaml
我有一个订单列表,当订单状态为Cancelled时,我想要闪烁文本.到目前为止,我的代码工作.但是,有时会抛出异常:
WinRT信息:无法解析TargetName lblOrderStatus
由于某种原因,可以找到lblOrderStatus.所以,我想使用"FindAncestor",但UWP中不存在FindAncestor.在uwp中是否有与FindAncestor等效的功能?
这是我的代码:
<ItemsControl x:Name="Orders" Grid.Row="1" Background="Transparent">
...
...
...
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
...
...
...
<Viewbox Grid.Column="3" StretchDirection="DownOnly" HorizontalAlignment="Right">
<TextBlock x:Name="lblOrderStatus" Text="{Binding Path=OrderItemStatus, Mode=OneWay}" FontSize="18">
<TextBlock.Resources>
<Storyboard x:Name="sbBlinking">
<DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Opacity)"
Storyboard.TargetName="lblOrderStatus"
From="1" To="0" AutoReverse="True" Duration="0:0:0.5" RepeatBehavior="Forever" />
</Storyboard>
</TextBlock.Resources>
<interactive:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding OrderItemStatus, Converter={StaticResource EnumToStringConverter}}" ComparisonCondition="Equal" Value="Cancelled">
<media:ControlStoryboardAction Storyboard="{StaticResource sbBlinking}" />
</core:DataTriggerBehavior>
</interactive:Interaction.Behaviors>
</TextBlock>
</Viewbox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)
BCA*_*BCA 12
考虑到我见过的所有解决方案,我觉得使用ElementName绑定是UWP最简单的解决方法,没有RelativeSource AncestorType绑定选项.
假设您已将Page其DataContext设置为带有命令的viewmodel MyCommand,并且您希望列表中的每个项目在单击其按钮时执行它:
<Page Name="thisPage">
...
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate>
<Button Command="{Binding ElementName=thisPage, Path=DataContext.MyCommand}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
Run Code Online (Sandbox Code Playgroud)
我对此解决方案的初始问题是,您无法将DataTemplate作为资源提取出来,以便在多个屏幕(甚至是对话框)上使用它; thisPage可能不存在于每个位置,或者可能不适合将根元素命名为"thisPage".
但是如果你使用一个约定,你在每个使用该DataTemplate的屏幕中包含一个令牌UI元素,并通过一致的名称引用它,它将起作用.默认情况下,此元素的DataContext将是您的ViewModel(假设您的根元素也是如此)
<Rectangle Name="VmDcHelper" Visibility="Collapsed"/>
Run Code Online (Sandbox Code Playgroud)
...然后在您的独立资源XAML文件中,您可以像这样编写DataTemplate:
<DataTemplate x:Key="MyDataTemplate">
<Button Command="{Binding ElementName=VmDcHelper, Path=DataContext.MyCommand}" />
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)
然后,在您使用该模板资源的每个页面/屏幕/对话框上,只需放入该Rectangle(或其他)的副本,一切都将在运行时正确绑定
这显然是一个黑客攻击解决方案,但是在考虑了它之后,它首先感觉不再像使用WPF的AncestorType那样黑客攻击了(必须确保你的祖先类型在所有地方始终保持一致)使用您的DataTemplate).
在XAML中,
您可以尝试使用RelativeSource,它提供了一种根据运行时对象图中的相对关系指定绑定源的方法。例如使用TemplatedParent:
Height="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Parent.ActualHeight}
Run Code Online (Sandbox Code Playgroud)
或者
<Binding RelativeSource="{RelativeSource TemplatedParent}" ></Binding>
Run Code Online (Sandbox Code Playgroud)
在代码中,您尝试使用 VisualTreeHelper.GetParent 方法。 https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.visualtreehelper.getparent
类似于下面的内容,这是一个实用函数的示例
internal static void FindChildren<T>(List<T> 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<T>(results, current);
}
}
Run Code Online (Sandbox Code Playgroud)
以下示例显示了检查元素的父元素的代码
((StackPanel)LinePane.Parent).ActualWidth;
Run Code Online (Sandbox Code Playgroud)
另外,这里有一篇很好的博客文章,展示了此类的实际应用。http://blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html