右键菜单关联viewModel 命令
在位编辑ListItem
Prism框架 MVVM 页面右键快捷菜单绑定 绑定 ViewModel方法。
0.引用库
<ItemGroup>
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
<PackageReference Include="Prism.DryIoc" Version="8.1.97" />
</ItemGroup>
MainWindow.xaml
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<StackPanel>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
<ContentControl prism:RegionManager.RegionName="ContentRegionB" />
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using Prism.Ioc;
using Prism.Regions;
using System.Windows;
namespace WpfApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
IContainerExtension _container;
IRegionManager _regionManager;
public MainWindow(IContainerExtension container, IRegionManager regionManager)
{
InitializeComponent();
_container = container;
_regionManager = regionManager;
regionManager.RegisterViewWithRegion("ContentRegion", typeof(Views.ViewA));
regionManager.RegisterViewWithRegion("ContentRegionB", typeof(Views.ViewB));
}
}
}
1. ViewA 视图
<UserControl x:Class="WpfApp.Views.ViewA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel>
<TextBlock>ViewA</TextBlock>
<TextBlock Text="{Binding Title}"/>
<ListView ItemsSource="{Binding Items}">
<ListView.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" x:Name="listView">
<MenuItem Header="New" Command="{Binding NewCommand}"/>
<MenuItem Header="Edit" Command="{Binding EditCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
<MenuItem Header="Delete" Command="{Binding DeleteCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</StackPanel>
</Grid>
</UserControl>
2. ViewA 模型
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
namespace WpfApp.ViewModels;
public class ViewAViewModel : BindableBase
{
private string _title = "Hello, Prism!";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private ObservableCollection<string> _items;
public ObservableCollection<string> Items
{
get { return _items; }
set { SetProperty(ref _items, value); }
}
public ICommand NewCommand { get; private set; }
public ICommand EditCommand { get; private set; }
public ICommand DeleteCommand { get; private set; }
public ViewAViewModel()
{
Items = new ObservableCollection<string> { "Item 1", "Item 2", "Item 3" };
NewCommand = new DelegateCommand(OnNew);
EditCommand = new DelegateCommand<string>(OnEdit);
DeleteCommand = new DelegateCommand<string>(OnDelete);
}
private void OnNew()
{
MessageBox.Show("new");
}
private void OnEdit(string item)
{
if (item == null)
{
// 处理空值的情况,例如记录日志或提示用户
Console.WriteLine("Selected item is null. Cannot edit.");
return;
}
MessageBox.Show($"Editing item: {item}");
// 编辑逻辑
Console.WriteLine($"Editing item: {item}");
}
private void OnDelete(string item)
{
if (item == null)
{
MessageBox.Show("Selected item is null. Cannot delete.");
// 处理空值的情况,例如记录日志或提示用户
Console.WriteLine("Selected item is null. Cannot delete.");
return;
}
if (Items.Contains(item))
{
MessageBox.Show($"Item '{item}' remove the collection.");
Items.Remove(item);
}
else
{
// 处理项目不在集合中的情况,例如记录日志或提示用户
MessageBox.Show($"Item '{item}' not found in the collection.");
Console.WriteLine($"Item '{item}' not found in the collection.");
}
}
}
viewA视图关键参数
ContextMenu 与viewA 的 DataContext绑定。
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" x:Name="listView">
<MenuItem Header="New" Command="{Binding NewCommand}"/>
<MenuItem Header="Edit" Command="{Binding EditCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
<MenuItem Header="Delete" Command="{Binding DeleteCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
3. ViewB 视图
ViewB.xaml
<UserControl x:Class="WpfApp.Views.ViewB"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp.Views"
xmlns:e="clr-namespace:WpfApp"
mc:Ignorable="d"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<e:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<e:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<DataTemplate x:Key="ItemTemplate">
<Grid>
<TextBlock Text="{Binding Text}" Visibility="{Binding IsEditing, Converter={StaticResource InverseBooleanToVisibilityConverter}}" VerticalAlignment="Center"/>
<TextBox Text="{Binding Text, Mode=TwoWay}"
Visibility="{Binding IsEditing, Converter={StaticResource BooleanToVisibilityConverter}}"
VerticalAlignment="Center">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding ConfirmEditCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="KeyDown">
<e:KeyDownCommandAction Command="{Binding ConfirmEditCommand}" Key="Enter"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid>
<StackPanel>
<ListView ItemsSource="{Binding Items}" ItemTemplate="{StaticResource ItemTemplate}" x:Name="listView">
<ListView.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Edit"
Command="{Binding PlacementTarget.SelectedItem.EditCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</StackPanel>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WpfApp.ViewModels;
namespace WpfApp.Views
{
/// <summary>
/// ViewB.xaml 的交互逻辑
/// </summary>
public partial class ViewB : UserControl
{
public ViewB()
{
InitializeComponent();
//DataContext = new ViewBViewModel();
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
var textBox = sender as TextBox;
if (textBox != null)
{
var itemViewModel = textBox.DataContext as ItemViewModel;
if (itemViewModel != null && itemViewModel.ConfirmEditCommand.CanExecute(null))
{
itemViewModel.ConfirmEditCommand.Execute(null);
}
}
}
}
}
4.ViewB 模型
ViewBViewModel.cs
using Prism.Commands;
using Prism.Mvvm;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace WpfApp.ViewModels;
public class ItemViewModel : BindableBase
{
private string _text;
public string Text
{
get { return _text; }
set { SetProperty(ref _text, value); }
}
private bool _isEditing;
public bool IsEditing
{
get { return _isEditing; }
set { SetProperty(ref _isEditing, value); }
}
public ICommand EditCommand { get; }
public ICommand ConfirmEditCommand { get; }
public ICommand CancelEditCommand { get; }
public ItemViewModel()
{
EditCommand = new DelegateCommand(OnEdit);
ConfirmEditCommand = new DelegateCommand(OnConfirmEdit);
CancelEditCommand = new DelegateCommand(OnCancelEdit);
}
private void OnEdit()
{
// MessageBox.Show("OnEdit");
IsEditing = true;
}
private void OnConfirmEdit()
{
IsEditing = false;
}
private void OnCancelEdit()
{
IsEditing = false;
}
}
public class ViewBViewModel : BindableBase
{
private ObservableCollection<ItemViewModel> _items;
public ObservableCollection<ItemViewModel> Items
{
get { return _items; }
set { SetProperty(ref _items, value); }
}
public ViewBViewModel()
{
Items = new ObservableCollection<ItemViewModel>
{
new ItemViewModel { Text = "Item 4" },
new ItemViewModel { Text = "Item 5" },
new ItemViewModel { Text = "Item 6" }
};
}
}
5. 转换类
BooleanToVisibilityConverter.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WpfApp;
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean)
{
return boolean ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility visibility)
{
return visibility == Visibility.Visible;
}
return false;
}
}
public class InverseBooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolean)
{
return boolean ? Visibility.Collapsed : Visibility.Visible;
}
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility visibility)
{
return visibility != Visibility.Visible;
}
return true;
}
}
6. 按键类
KeyDownCommandAction.cs
using Microsoft.Xaml.Behaviors;
using System.Windows;
using System.Windows.Input;
namespace WpfApp;
public class KeyDownCommandAction : TriggerAction<UIElement>
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(KeyDownCommandAction), new PropertyMetadata(null));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public Key Key { get; set; }
protected override void Invoke(object parameter)
{
var keyEventArgs = parameter as KeyEventArgs;
if (keyEventArgs != null && keyEventArgs.Key == Key)
{
if (Command != null && Command.CanExecute(null))
{
Command.Execute(null);
}
}
}
}