【问题标题】:UWP ListView Item context menuUWP ListView 项目上下文菜单
【发布时间】:2023-03-13 23:35:01
【问题描述】:

我正在互联网上搜索如何为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 项创建上下文菜单。

【问题讨论】:

    标签: xaml win-universal-app contextmenu


    【解决方案1】:

    在数据模板中添加弹出窗口。使用命令处理事件。 在此处查看示例代码:

    <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

    【讨论】:

      【解决方案2】:

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

      对于这个问题,如果你像这样向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;
      }
      

      在这种情况下,“a”会直接获取点击项的字符串格式内容。

      如果您像这样使用DataTemplate 将数据添加到ListView

      <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" });
      }
      

      “List”类在这里测试很简单:

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

      那么我们也可以在RightTapped事件中获取DataContext

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

      但这一次,“a”实际上是item内部的'List'对象(请参考“List”类),因为item的内容现在是一个'List'对象,不再是字符串了.所以我们可以像这样获取这个对象的 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,我不确定在移动设备上长按是否会显示上下文菜单。

      我认为这里的“长按”事件表示像这样的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就可以得到item的Context了。

      【讨论】:

        【解决方案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 
         }
        

        【讨论】:

        • 感谢回复。我要试试。但是触发此事件的事件仍然是右键单击列表视图。所以它会被触发 e。 G。当我右键单击列表视图中组的标题或边框时。我期待一些非常容易实现的东西,因为这是常见的功能。
        • 绑定是有意义的,但它总是null。将Command 属性附加到任何东西上都没有成功。
        • 尝试使用 prism 框架中的 BehaviorsInvokeCommandAction
        猜你喜欢
        • 2016-10-06
        • 1970-01-01
        • 2020-10-13
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-14
        • 1970-01-01
        相关资源
        最近更新 更多