UWP:从弹出菜单项单击处理程序查找父项
使用UWP,我有一个UWP:从弹出菜单项单击处理程序查找父项,uwp,flyout,Uwp,Flyout,使用UWP,我有一个列表视图,其中每个项目都包含一个按钮。点击该按钮将打开一个菜单out。点击其中一个弹出式选项将触发单击事件 在事件处理程序中,如何找到父按钮或父ListView项 这是我的XAML的摘录。具体来说,我想在OnItemEdit处理程序中查找“Note”元素 <Page.Resources> <ResourceDictionary> <DataTemplate x:Key="NoteItemTemplate">
列表视图
,其中每个项目都包含一个按钮
。点击该按钮将打开一个菜单out
。点击其中一个弹出式选项将触发单击事件
在事件处理程序中,如何找到父按钮或父ListView
项
这是我的XAML的摘录。具体来说,我想在OnItemEdit
处理程序中查找“Note”元素
<Page.Resources>
<ResourceDictionary>
<DataTemplate x:Key="NoteItemTemplate">
<Grid>
<Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>
<TextBox Name="Note" />
<Button>
<Image Source="..." />
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="Edit" Click="OnItemEdit" />
<MenuFlyoutItem Text="Delete" Click="OnItemDelete" />
</MenuFlyout>
</Button.Flyout>
</Button>
</Grid>
</DataTemplate>
...
<local:DetailItemSelector x:Key="DetailItemSelector"
NoteItemTemplate="{StaticResource NoteItemTemplate}"
...
/>
</ResourceDictionary>
</Page.Resources>
<ListView
x:Name = "DetailList"
ItemsSource = "{x:Bind DetailListItems}"
ItemTemplateSelector = "{StaticResource DetailItemSelector}">
</ListView>
编辑-解决方案
如果没有更好的办法,这里有一个解决办法也不错。诀窍是使用弹出按钮base.AttachedFlyout
而不是按钮.Flyout
<DataTemplate x:Key="NoteItemTemplate">
<Grid>
<Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>
<TextBox ... Name="Note" />
<Button ... Click=="onMoreClicked">
<Image Source="..." />
FlyoutBase.AttachedFlyout
<MenuFlyout>
<MenuFlyoutItem Text="Edit" Click="OnItemEdit" />
<MenuFlyoutItem ... />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
</Button>
</Grid>
</DataTemplate>
在您的场景中,您可以添加一个成员变量来保存表示ListViewItem
的Grid
实例,以供以后访问。将PointerEntered
事件添加到Grid
面板。当您单击一个项目的按钮弹出一个弹出按钮时,将首先触发该项目的网格的PointerEntered
事件处理程序。在PointerEntered
事件处理程序中,将sender
分配给成员变量。然后您可以访问事件处理程序中的网格
您可以检查以下内容作为示例:
//MainPage.xaml
<DataTemplate x:Key="NoteItemTemplate">
<Grid PointerEntered="Grid_PointerEntered" >
<Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>
……
</Grid>
</DataTemplate>
//MainPage.xaml.cs
private Grid myPanel;
private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
myPanel = sender as Grid;
}
private void OnItemEdit(object sender, RoutedEventArgs e)
{
//Change the value of index to adjust your scenario
var box = VisualTreeHelper.GetChild(myPanel, 0) as TextBox;
}
具体地说,我想在Medit处理程序中查找“Note”元素
假设将DataTemplate
应用于一个“Note”,这应该与将sender
参数的DataContext
转换为Note
一样简单(或者无论您的类型被称为什么):
如果需要对“节点”TextBox
元素的引用,可以在可视化树中找到它:
private void OnItemEdit(object sender, RoutedEventArgs e)
{
MenuFlyoutItem menuFlyoutItem = (MenuFlyoutItem)sender;
DependencyObject container = DetailList.ContainerFromItem(menuFlyoutItem.DataContext);
TextBox note = FindVisualChild<TextBox>(container);
...
}
private static T FindVisualChild<T>(DependencyObject visual) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(visual, i);
if (child != null)
{
T correctlyTyped = child as T;
if (correctlyTyped != null)
return correctlyTyped;
T descendent = FindVisualChild<T>(child);
if (descendent != null)
return descendent;
}
}
return null;
}
private void-onite-medit(对象发送方,路由目标)
{
MenuFlyoutItem MenuFlyoutItem=(MenuFlyoutItem)发送方;
DependencyObject容器=DetailList.ContainerFromItem(menuFlyoutItem.DataContext);
TextBox note=FindVisualChild(容器);
...
}
私有静态T FindVisualChild(DependencyObject可视),其中T:DependencyObject
{
for(int i=0;i
我一定是误解了你的解释。如果列表中有10个项目,如何确定哪个项目(以及哪个文本框)触发了Onite Medit事件?看来你是任意挑选了一个(可能是第一个)。这不是任意的。在单击某个按钮弹出弹出型按钮之前,必须将指针移动到包含该弹出型按钮的ListViewItem上。此时,将调用PointerEntered事件处理程序将ListViewItem的网格分配给成员变量,并且在弹出按钮隐藏之前不会调用其他ListViewItem的PointerEntered事件处理程序。当您单击ListViewItem的按钮时,这可以确保存储在成员变量中的网格始终是其按钮被单击的网格。啊,对不起,我显然不明白“PointerEntered”的作用。不幸的是,我认为这种方法行不通。我没有提到(因为我认为会有一个直截了当的解决方案)它需要与触摸屏一起工作,我不认为“指针连接”会起到任何作用(我将对此进行测试并查看)。正确的解决方案是处理“按钮”单击事件,缓存对按钮(或父项)的引用,然后将单击事件转发给原始处理程序。我找不到办法。另外,“指针式”方法有些脆弱。我已经更新了答案,您可以尝试看看更新是否能满足您的要求。我已经有了解决方法,我认为这更好。我会把它添加到OP中作为参考。@PeriHartman:你试过这个吗?对不起,还没有。我肯定会的。可能是星期四。如果我按照你的建议做,DataContext
指向注释数据(一个文本字符串),而不是注释文本框。我已经对此进行了研究和试验,但不知道如何将DataContext
设置为note控件。我尝试将DataContext=“{StaticResource Item}”
添加到“编辑”MenuFlyoutItem
,但这导致运行时异常。对于这种情况,在线搜索没有发现任何结果。我想我可以使用搜索ListView
来搜索包含引用注释数据的项目。很简单,但我只想在没有更直接的解决方案时这样做。@PeriHartman:请参阅我的编辑。它应该能回答你的问题。
//MainPage.xaml
<DataTemplate x:Key="NoteItemTemplate">
<Grid PointerEntered="Grid_PointerEntered" >
<Grid.ColumnDefinitions> ... </Grid.ColumnDefinitions>
……
</Grid>
</DataTemplate>
//MainPage.xaml.cs
private Grid myPanel;
private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
myPanel = sender as Grid;
}
private void OnItemEdit(object sender, RoutedEventArgs e)
{
//Change the value of index to adjust your scenario
var box = VisualTreeHelper.GetChild(myPanel, 0) as TextBox;
}
private void OnItemEdit(object sender, RoutedEventArgs e)
{
//Find the item be clicked
object clickedItem=new object();
foreach(var cur in DetailList.Items)
{
if(cur.ToString()==(sender as MenuFlyoutItem).DataContext.ToString())
{
clickedItem = cur;
break;
}
}
//
var type = DetailList.ContainerFromItem(clickedItem);
var item = type as ListViewItem;
var box = VisualTreeHelper.GetChild(item.ContentTemplateRoot as DependencyObject, 0);
string text = (box as TextBox).Text;
}
private void OnItemEdit(object sender, RoutedEventArgs e)
{
MenuFlyoutItem menuFlyoutItem = (MenuFlyoutItem)sender;
var note = menuFlyoutItem.DataContext as YourNoteClass;
...
}
private void OnItemEdit(object sender, RoutedEventArgs e)
{
MenuFlyoutItem menuFlyoutItem = (MenuFlyoutItem)sender;
DependencyObject container = DetailList.ContainerFromItem(menuFlyoutItem.DataContext);
TextBox note = FindVisualChild<TextBox>(container);
...
}
private static T FindVisualChild<T>(DependencyObject visual) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(visual, i);
if (child != null)
{
T correctlyTyped = child as T;
if (correctlyTyped != null)
return correctlyTyped;
T descendent = FindVisualChild<T>(child);
if (descendent != null)
return descendent;
}
}
return null;
}