【C#】WPF给ListBox中的每一项添加右键菜单功能

[复制链接]
发表于 2025-10-19 06:31:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

  • 媒介

    • 一、ContextMenu控件

      • ContextMenu 是实如今控件上右键点击时体现一个上下文菜单。
      • ContextMenu菜单可以添加多个菜单项(MenuItem),每个菜单项可以绑定指定变乱或下令。

    • 二、ContextMenu 的 DataContext 绑定标题

      • 1、在ListBox 控件中创建DataTemplate,绑定命据源为DataCollection。
      • 2、在ListBox创建了TextBlock控件。
      • 3、在TextBlock内里添加ContextMenu右键菜单。

    • ContextMenu 默认不继承父控件的 DataContext
    • 如果须要显式地绑定 DataContext,须要使用 PlacementTarget  逐级向上绑定到  DataContext。
      1. DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}"
      复制代码
    • 但是,在此案例中如果将 【MenuDownItemCommand】下令创建在 【DataListViewModel 】中,然后对菜单项举行下令绑定,是无法见效的。
      1. <MenuItem Name="Delete" Header="删除" Command="{Binding MenuDownItemCommand}" CommandParameter="Delete"/>
      复制代码
    • 由于ListBox绑定的是DataCollection,DataCollection聚集中的对象是DataModel ,而DataModel中又没有创建MenuDownItemCommand下令。
    • 以是准确的做法是将MenuDownItemCommand 创建在DataModel这个类中。
      1. public class DataModel : PropertyChangedBase
      2. {
      3.     public string Content { get; set; }
      4.     public string Date { get; set; }
      5.     public ICommand MenuDownItemCommand { get; set; }
      6. }
      复制代码

  • 下面是一个在WPF中使用ContextMenu右键菜单的例子:

    • 该案例使用DataContext数据上下文实现前后端绑定。

      • 1、创建一个属性变动基类 PropertyChangedBase,实现属性厘革变乱。
      • 2、创建数据聚集视图模子类,处置惩罚视图视图和模子之间的数据交互。
      • 3、创建DataModel类,作为数据模子,生存到聚集中。
      • 4、创建下令,实现下令绑定,触发干系利用。





  • 三、效果预览

    • 1、界面效果



  • 2、左键


  • 3、右键




  • 四、前端页面代码
    1. <UserControl x:Class="CS学习之WPF右键菜单.DataListView"
    2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6.              xmlns:local="clr-namespace:CS学习之WPF右键菜单"
    7.              xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors"
    8.              mc:Ignorable="d"
    9.              d:DesignHeight="450" d:DesignWidth="800">
    10.     <UserControl.DataContext>
    11.         <local:DataListViewModel x:Name="ViewModel"/>
    12.     </UserControl.DataContext>
    13.     <Grid Background="#FFFFFF">
    14.         <ScrollViewer Background="#AEAEAE" x:Name="RecordScrollViewer" HorizontalScrollBarVisibility="Visible"
    15.               VerticalScrollBarVisibility="Visible">
    16.             <ListBox Margin="5" ItemsSource="{Binding DataCollection}">
    17.                 <ListBox.ItemTemplate>
    18.                     <DataTemplate>
    19.                         <StackPanel Orientation="Vertical" Margin="10,5,0,0">
    20.                             <TextBlock Name="TitleDate" FontSize="14"  Margin="10,5,0,0" Foreground="#BBBBBB" Text="{Binding Date}" >
    21.                               
    22.                             </TextBlock>
    23.                             <!-- 显示消息内容 -->
    24.                             <TextBlock FontSize="14"  Margin="10,5,0,0"
    25.                                Text="{Binding Content}" >
    26.                                 <TextBlock.ContextMenu>
    27.                                     <ContextMenu Name="RightKeyMenu" DataContext="{Binding PlacementTarget.DataContext,RelativeSource={RelativeSource Self}}">   
    28.                                         <MenuItem Name="Delete" Header="删除"
    29.                                             Command="{Binding MenuDownItemCommand}" CommandParameter="{Binding}" />
    30.                                         <Separator/>
    31.                                     </ContextMenu>
    32.                                 </TextBlock.ContextMenu>
    33.                                 <behavior:Interaction.Triggers>
    34.                                     <!--鼠标点击命令事件-->
    35.                                     <behavior:EventTrigger EventName="PreviewMouseDown">
    36.                                         <behavior:InvokeCommandAction
    37.                                          Command="{Binding DataContext.DataMouseDownCommand,
    38.                                                    RelativeSource={RelativeSource AncestorType=ListBox}}"
    39.                                                    PassEventArgsToCommand="True">
    40.                                         </behavior:InvokeCommandAction>
    41.                                     </behavior:EventTrigger>
    42.                                 </behavior:Interaction.Triggers>
    43.                             </TextBlock>
    44.                         </StackPanel>
    45.                     </DataTemplate>
    46.                 </ListBox.ItemTemplate>
    47.             </ListBox>
    48.         </ScrollViewer>
    49.     </Grid>
    50. </UserControl>
    复制代码
  • 1、属性变动 == PropertyChangedBase
    1.         ///属性变更基类
    2.                 public class PropertyChangedBase: INotifyPropertyChanged
    3.                 {
    4.                         public event PropertyChangedEventHandler? PropertyChanged;
    5.                         protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    6.                         {
    7.                                 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    8.                         }
    9.                 }
    复制代码
  • 2、数据聚集视图模子 == DataListViewModel
    1. public class DataListViewModel : PropertyChangedBase
    2. {
    3.     private ObservableCollection<DataModel> _dataCollection;
    4.     public ObservableCollection<DataModel> DataCollection
    5.     {
    6.         get => _dataCollection;
    7.         set
    8.         {
    9.             if (_dataCollection != value)
    10.             {
    11.                 _dataCollection = value;
    12.                 OnPropertyChanged();
    13.             }
    14.         }
    15.     }
    16.     public ICommand DataMouseDownCommand { get; set; }
    17.     //无参构造
    18.     public DataListViewModel()
    19.     {
    20.         Initialize();
    21.     }
    22.     /// <summary>
    23.     /// 初始化数据
    24.     /// </summary>
    25.     private void Initialize()
    26.     {
    27.         DataMouseDownCommand = new RelayCommand(OnDataMouseDown);
    28.         DataCollection = new ObservableCollection<DataModel>();
    29.         for (int i = 0; i < 10; i++)
    30.         {
    31.             DataModel dataModel = new DataModel();
    32.             dataModel.Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    33.             dataModel.Content = $"测试数据0000{i}";
    34.             dataModel.MenuDownItemCommand = new RelayCommand(OnMenuItemMouseDown);
    35.             DataCollection.Add(dataModel);
    36.         }
    37.     }
    38.     private void OnDataMouseDown(object args)
    39.     {
    40.         //业务处理
    41.     }
    42.     public void OnMenuItemMouseDown(object args)
    43.     {
    44.         //业务处理
    45.         MessageBox.Show("右键菜单被点击了");
    46.     }
    47. }
    复制代码
  • 3、数据模子类 == DataModel
    1. public class DataModel : PropertyChangedBase
    2. {
    3.     public string Content { get; set; }
    4.     public string Date { get; set; }
    5.     public ICommand MenuDownItemCommand { get; set; }
    6. }
    复制代码
  • 4、下令 == RelayCommand
    1. public class RelayCommand : ICommand
    2. {
    3.      private readonly Action<object> _execute;
    4.      private readonly Predicate<object> _canExecute;
    5.      public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
    6.      {
    7.          _execute = execute ?? throw new ArgumentNullException(nameof(execute));
    8.          _canExecute = canExecute;
    9.      }
    10.      public bool CanExecute(object parameter)
    11.      {
    12.          return _canExecute == null || _canExecute(parameter);
    13.      }
    14.      public void Execute(object parameter)
    15.      {
    16.          _execute(parameter);
    17.      }
    18.      public event EventHandler CanExecuteChanged
    19.      {
    20.          add { CommandManager.RequerySuggested += value; }
    21.          remove { CommandManager.RequerySuggested -= value; }
    22.      }
    23. }
    复制代码



  • 结语

    • 可以使用ContextMenu 在控件上实现右键点击体现菜单。
    • 可以给菜单添加多个菜单项(MenuItem),每个菜单项可以绑定变乱或下令。
    • ContextMenu 默认不继承父控件的 DataContext,但可以使用 PlacementTarget  逐级向上绑定到  DataContext。
    • 既是分享,也是备份。




  • 末了

    • 如果你以为这篇文章对你有资助,不妨点个赞支持一下!
    • 如有疑问,接待批评区留言。


回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表