如何将 ContextFlyout 与 ListView 一起使用?

How do you use the ContextFlyout with a ListView?

我正在尝试将 MenuFlyout 添加到我的 UWP 应用程序以支持控制器。问题是我不知道如何确定哪个 ListViewItem 实际触发了事件。

代码隐藏

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        this.DataContext = new List<String>{ "Item 1", "Item 2", "Item 3"};
    }

    private void ChoiceA_Click(object sender, RoutedEventArgs e)
    {
        // What was clicked?
    }
}

XAML

<ListView ItemsSource="{Binding}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="ContextFlyout">
                    <Setter.Value>
                        <MenuFlyout>
                            <MenuFlyoutItem Text="Choice A" Click="ChoiceA_Click" />
                            <MenuFlyoutItem Text="Choice B" />
                        </MenuFlyout>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

试试这个解决方案。首先,您需要修改 XAML,因为 class ListViewItem 没有 属性 ContextFlyout。您需要在 ItemTemplate 中使用 FlyoutBase.AttachedFlyout。

<ListView ItemsSource="{Binding}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Tapped="TextBlock_Tapped">
                <FlyoutBase.AttachedFlyout>
                    <MenuFlyout>
                        <MenuFlyoutItem Text="{Binding}" IsHitTestVisible="False" FontWeight="Bold" FontSize="24" />
                        <MenuFlyoutItem Text="Choice A" Click="MenuFlyoutItem_Click" />
                        <MenuFlyoutItem Text="Choice B" />
                    </MenuFlyout>
                </FlyoutBase.AttachedFlyout>
            </TextBlock>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这里是代码隐藏:

public 密封部分 class MainPage : Page { public 主页() { this.InitializeComponent(); this.DataContext = 新列表 { "Item 1", "Item 2", "Item 3" }; }

    private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e)
    {
        var fe = sender as FrameworkElement;
        var value = fe.DataContext.ToString();
        await new MessageDialog(value).ShowAsync();
    }

    private void TextBlock_Tapped(object sender, TappedRoutedEventArgs e)
    {
        var fe = sender as FrameworkElement;
        var menu = Flyout.GetAttachedFlyout(fe);
        menu.ShowAt(fe);
    }
}

您需要检测 ListView 中每个项目的 ItemTapped 事件,以便显示菜单。

我刚刚用本地机器和移动模拟器测试了你的代码,你的 MenuFlyout 只能在 PC 上通过右击 ListView 来显示,那么这是一个解决方案,你可以找到OriginalSourceListViewRightTapped 事件中,然后得到这个 OriginalSourceDataContext 例如这样:

private FrameworkElement originalSource;
private void ChoiceA_Click(object sender, RoutedEventArgs e)
{
    var itemdatacontext = originalSource.DataContext;
}

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    originalSource = (FrameworkElement)e.OriginalSource;
}

绑定到 MenuFlyoutOpening 事件。在事件处理程序中,senderMenuFlyout 本身。在那里你会找到指向 ListViewItem.

Target 属性

根据您的示例,您的 XAML 可能如下所示:

<ListView ItemsSource="{Binding}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="ContextFlyout">
                    <Setter.Value>
                        <MenuFlyout Opening="ListView_Opening">
                            <MenuFlyoutItem Text="Choice A" Click="ChoiceA_Click" />
                            <MenuFlyoutItem Text="Choice B" />
                        </MenuFlyout>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>

你的代码是这样的:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        this.DataContext = new List<String>{ "Item 1", "Item 2", "Item 3"};
    }

    private string ListViewItemString;

    private void ChoiceA_Click(object sender, RoutedEventArgs e)
    {
        // What was clicked?
        var clickedItem = ListViewItemString;
    }

    private void ListView_Opening(object sender, object e)
    {
        ListViewItemString = ((sender as MenuFlyout)?.Target as ListViewItem)?.Content as string;
    }
}