UWP ListView项目上下文菜单

时间:2016-04-20 11:01:10

标签: xaml win-universal-app contextmenu

我正在搜索互联网,了解如何为ListView添加上下文菜单。到目前为止,我发现了一个实际显示上下文的文件

<ListView>
    ...
    RightTapped="ContactsListView_RightTapped" >
    ...
    <ListView.Resources>
        <MenuFlyout x:Name="allContactsMenuFlyout">
            <MenuFlyout.Items>
                <MenuFlyoutItem x:Name="Edit"  Text="Edit"/>
                <MenuFlyoutItem x:Name="Remove" Text="Remove"    Click="Remove_Click"/>
            </MenuFlyout.Items>
        </MenuFlyout>
    </ListView.Resources>
    ...
</ListView>

private void ContactsListView_RightTapped(object sender, RightTappedRoutedEventArgs e) {
    ListView listView = (ListView)sender;
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView));
}

private void Remove_Click(object sender, RoutedEventArgs e) {

}

问题是我无法获得显示上下文菜单的项目。另一个问题是上下文菜单也显示在列表视图项之外(例如,在边界上)。由于触发的事件是RightTapped,我不确定是否会在长按移动设备上显示上下文菜单。我无法测试它,因为我的模拟器当前不工作。由于它应该是通用的Windows应用程序,我期待一些非常简单有效的方法为ListView项目创建上下文菜单。

3 个答案:

答案 0 :(得分:15)

  

问题是我无法获得显示上下文菜单的项目。

对于此问题,如果您将数据添加到ListView,请执行以下操作:

<ListView RightTapped="ListView_RightTapped">
    <x:String>First Item</x:String>
    <x:String>Second Item</x:String>
    <x:String>Third Item</x:String>
    <x:String>Fourth Item</x:String>

    <ListView.Resources>
        <MenuFlyout x:Name="allContactsMenuFlyout">
            <MenuFlyout.Items>
                <MenuFlyoutItem x:Name="Edit"  Text="Edit" />
                <MenuFlyoutItem x:Name="Remove" Text="Remove"    Click="Remove_Click" />
            </MenuFlyout.Items>
        </MenuFlyout>
    </ListView.Resources>
</ListView>

您可以在RightTapped事件中获取该项目的上下文,如下所示:

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    ListView listView = (ListView)sender;
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView));
    var a = ((FrameworkElement)e.OriginalSource).DataContext;
}

在这种情况下,&#34; a&#34;将直接获取被点击项目的字符串格式内容。

如果您使用ListView将数据添加到DataTemplate,请执行以下操作:

<ListView RightTapped="ListView_RightTapped" ItemsSource="{x:Bind list}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding text}" />
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.Resources>
        <MenuFlyout x:Name="allContactsMenuFlyout">
            <MenuFlyout.Items>
                <MenuFlyoutItem x:Name="Edit"  Text="Edit" />
                <MenuFlyoutItem x:Name="Remove" Text="Remove"    Click="Remove_Click" />
            </MenuFlyout.Items>
        </MenuFlyout>
    </ListView.Resources>
</ListView>

通常在使用DataTemplate时,我们按ObservableCollection添加数据:

private ObservableCollection<List> list = new ObservableCollection<List>();

public MainPage()
{
    this.InitializeComponent();
    list.Clear();
    list.Add(new List { text = "Item 1" });
    list.Add(new List { text = "Item 2" });
    list.Add(new List { text = "Item 3" });
    list.Add(new List { text = "Item 4" });
    list.Add(new List { text = "Item 5" });
}

&#34;列表&#34;这里的课程非常简单:

public class List
{
    public string text { get; set; }
}

然后我们也可以在DataContext事件中获取RightTapped

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    ListView listView = (ListView)sender;
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView));
    var a = ((FrameworkElement)e.OriginalSource).DataContext;
}

但这一次,&#34; a&#34;实际上是&#39; List&#39;对象(请参阅&#34;列表&#34;类),因为项目的内容现在是&#39;列表&#39;对象,不再是字符串了。所以我们可以得到这个对象的text属性:

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    ListView listView = (ListView)sender;
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView));
    var a = ((FrameworkElement)e.OriginalSource).DataContext as List;
    var content = a.text;
}

我认为最终你想编辑Flyout的按钮点击事件中的内容,你可以这样做:

private string content;

private void ListView_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    ListView listView = (ListView)sender;
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView));
    var a = ((FrameworkElement)e.OriginalSource).DataContext as List;
    content = a.text;
}

private void Remove_Click(object sender, RoutedEventArgs e)
{
    foreach (var item in list.ToList())
    {
        if (item.text == content)
        {
            list.Remove(item);
        }
    }
    content = "";
}
  

另一个问题是上下文菜单也显示在列表视图项之外(例如,在边框上)。

你能解释一下吗?我无法理解它。您的意思是在Flyout中显示内容?如果是这样,我认为上面的方法可以解决这个问题。如果没有,你可以发表评论,我会看看是否可以解决这个问题。

  

由于触发的事件是RightTapped,我不确定是否会在长按移动设备上显示上下文菜单。

我认为&#34;长按&#34; event在这里表示Holding这样的事件?

private void ListView_Holding(object sender, HoldingRoutedEventArgs e)
{
    ListView listView = (ListView)sender;
    allContactsMenuFlyout.ShowAt(listView, e.GetPosition(listView));
    var a = ((FrameworkElement)e.OriginalSource).DataContext as List;
    content = a.text;
}

我只是在移动模拟器上测试它,它工作正常。虽然我在这里写了一个很长的答案,但关键点很简单,你可以使用((FrameworkElement)e.OriginalSource).DataContext来获取项目的上下文。

答案 1 :(得分:3)

使用Command而不是Click事件。您可以在CommandParameter中传递单击的项目

   <MenuFlyout x:Name="allContactsMenuFlyout">
                <MenuFlyout.Items>
                    <MenuFlyoutItem x:Name="Edit"  Text="Edit"/>
                    <MenuFlyoutItem x:Name="Remove" Text="Remove"   Command="{Binding Path=DataContext.DeleteItemTappedCommand , ElementName=ListViewName}" CommandParameter="{Binding }"/>
                </MenuFlyout.Items>
            </MenuFlyout>

In viewModel.cs
  public DelegateCommand<object> DeleteItemTappedCommand { get; set; }

public viewModel()
{
 DeleteItemTappedCommand = new DelegateCommand<object>(DeleteItemClicked);
}
 private void DeleteItemClicked(object obj)
 {
//Your code. Here obj is clicked  item 
 }

答案 2 :(得分:0)

在datatemplate中添加弹出按钮。使用命令处理事件。 请在此处查看示例代码:

<DataTemplate x:Name="ListItemTemplate" >
    <Grid  x:Name="gridItem"  RightTapped="gridItem_RightTapped">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Image Name="imgProduct" Width="50" Height="50" Grid.Column="0" Source="{Binding ProductUrl}" Margin="0,5,10,5" VerticalAlignment="Center" ></Image>
        <TextBlock Name="tbName" Text="{Binding Name}" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Stretch"  ></TextBlock>
        <FlyoutBase.AttachedFlyout>
            <MenuFlyout>
                <MenuFlyoutItem Text="Delete" Command="{Binding DataContext.DeleteCommand, ElementName=contentGrid}" CommandParameter="{Binding}"  />
            </MenuFlyout>
        </FlyoutBase.AttachedFlyout>
    </Grid>
</DataTemplate>

代码背后:

private void gridItem_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
    FlyoutBase.ShowAttachedFlyout(sender as FrameworkElement);
}

您可以在此处获得完整的解决方案:https://code.msdn.microsoft.com/How-to-implement-flyout-ef52517f