UWP/WinRT: 如何从模板所绑定的项访问模板生成的控件?
UWP/WinRT: How to access a control generated by a template from the item it is bound to?
我有一个数据透视表,其内容是使用数据绑定生成的。对于向量中的每个项目,生成一个网格,并在每个网格内生成一个文本块。
如果我有来自矢量的特定项目,我如何在我的代码后面访问从它生成的相应 TextBlock?
我的第一个想法是将每个 TextBlock 的 x:name
属性 设置为每个项目中保存的唯一标识符,然后我可以简单地在标识符上调用 FrameworkElement::FindName()
,但显然 x:name
属性 不允许使用数据绑定生成。
我看到可以朝另一个方向前进,并通过调用其 DataContext 从 TextBlock 中提取项目。
我发现我可以使用 VisualTreeHelper 开始逐个搜索 TextBlock 控件。不过,我在查找 C++ 中的示例时遇到了问题,在此上下文中如何使用它?这是唯一的方法吗?这么简单的事情似乎很复杂。还有更多的方法吗,正确的方法是什么?
我在 XAML 中使用 C++/CX。
Pivot 是 ItemsControl 的后代,因此:
使用 https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemscontrol.containerfromitem.aspx or https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemscontrol.containerfromindex.aspx 并加上 VisualTreeHelper。 (如果 ItemTemplate 是固定的,你甚至可以做类似 ((Grid)*YourReturnedDependencyObject*).Children[0] as TextBlock
的事情,所以你甚至不需要 VisualTreeHelper。)
为了其他可能处于类似情况的人的利益,这是我最终实施的解决方案,但我将 Tamás Deme 的回答标记为已接受,因为它让我得到了这个结果。
// I am using dynamic_casts to determine if a returned object is of the expected class
auto currentPivotItem = dynamic_cast<PivotItem^>(myPivot->ContainerFromItem(myItem));
if (currentPivotItem != nullptr && VisualTreeHelper::GetChildrenCount(currentPivotItem) > 0)
{
auto currentGrid = dynamic_cast<Grid^>(VisualTreeHelper::GetChild(currentPivotItem, 0));
if (currentGrid != nullptr && VisualTreeHelper::GetChildrenCount(currentGrid) == 1)
{ // Through trial and error, I discovered there are 2 layers of unknownItems I need to traverse
auto unknownItem = VisualTreeHelper::GetChild(currentGrid, 0);
if (unknownItem != nullptr && VisualTreeHelper::GetChildrenCount(unknownItem) == 1)
{
auto unknownItem2 = VisualTreeHelper::GetChild(unknownItem, 0);
if (unknownItem2 != nullptr && VisualTreeHelper::GetChildrenCount(unknownItem2) == 2)
{ // Based on my XAML, the TextBlock will always be the child at index 1
auto currentTextBlock = dynamic_cast<TextBlock^>(VisualTreeHelper::GetChild(unknownItem2, 1));
if (currentTextBlock != nullptr) currentTextBlock->Text = "Success!"
}
}
}
}
我有一个数据透视表,其内容是使用数据绑定生成的。对于向量中的每个项目,生成一个网格,并在每个网格内生成一个文本块。
如果我有来自矢量的特定项目,我如何在我的代码后面访问从它生成的相应 TextBlock?
我的第一个想法是将每个 TextBlock 的 x:name
属性 设置为每个项目中保存的唯一标识符,然后我可以简单地在标识符上调用 FrameworkElement::FindName()
,但显然 x:name
属性 不允许使用数据绑定生成。
我看到可以朝另一个方向前进,并通过调用其 DataContext 从 TextBlock 中提取项目。
我发现我可以使用 VisualTreeHelper 开始逐个搜索 TextBlock 控件。不过,我在查找 C++ 中的示例时遇到了问题,在此上下文中如何使用它?这是唯一的方法吗?这么简单的事情似乎很复杂。还有更多的方法吗,正确的方法是什么?
我在 XAML 中使用 C++/CX。
Pivot 是 ItemsControl 的后代,因此:
使用 https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemscontrol.containerfromitem.aspx or https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.itemscontrol.containerfromindex.aspx 并加上 VisualTreeHelper。 (如果 ItemTemplate 是固定的,你甚至可以做类似 ((Grid)*YourReturnedDependencyObject*).Children[0] as TextBlock
的事情,所以你甚至不需要 VisualTreeHelper。)
为了其他可能处于类似情况的人的利益,这是我最终实施的解决方案,但我将 Tamás Deme 的回答标记为已接受,因为它让我得到了这个结果。
// I am using dynamic_casts to determine if a returned object is of the expected class
auto currentPivotItem = dynamic_cast<PivotItem^>(myPivot->ContainerFromItem(myItem));
if (currentPivotItem != nullptr && VisualTreeHelper::GetChildrenCount(currentPivotItem) > 0)
{
auto currentGrid = dynamic_cast<Grid^>(VisualTreeHelper::GetChild(currentPivotItem, 0));
if (currentGrid != nullptr && VisualTreeHelper::GetChildrenCount(currentGrid) == 1)
{ // Through trial and error, I discovered there are 2 layers of unknownItems I need to traverse
auto unknownItem = VisualTreeHelper::GetChild(currentGrid, 0);
if (unknownItem != nullptr && VisualTreeHelper::GetChildrenCount(unknownItem) == 1)
{
auto unknownItem2 = VisualTreeHelper::GetChild(unknownItem, 0);
if (unknownItem2 != nullptr && VisualTreeHelper::GetChildrenCount(unknownItem2) == 2)
{ // Based on my XAML, the TextBlock will always be the child at index 1
auto currentTextBlock = dynamic_cast<TextBlock^>(VisualTreeHelper::GetChild(unknownItem2, 1));
if (currentTextBlock != nullptr) currentTextBlock->Text = "Success!"
}
}
}
}