WPF:如何使用MVVM将命令绑定到ListBoxItem?

我刚开始学习MVVM。 我通过遵循这个MVVM教程从头开始制作应用程序(我强烈推荐给所有MVVM初学者)。 基本上,我到目前为止创建的是一些用户添加他或她的数据的文本框,一个保存该数据的按钮,随后用所有条目填充ListBox。

这就是我遇到的问题:我希望能够双击ListBoxItem并触发我创建并添加到ViewModel的命令。 我不知道如何完成XAML方面,即我不知道如何将该命令绑定到ListBox(Item)。

这是XAML:

...  ... 

这是ViewModel:

 public class MainWindowViewModel : DependencyObject { ... public IEntriesProvider Entries { get { return entries; } } private IEntriesProvider entries; public OpenEntryCommand OpenEntryCmd { get; set; } public MainWindowViewModel(IEntriesProvider source) { this.entries = source; ... this.OpenEntryCmd = new OpenEntryCommand(this); } ... } 

最后,这是我想在用户双击EntriesListBox中的项目后执行的OpenEntryCommand:

 public class OpenEntryCommand : ICommand { private MainWindowViewModel viewModel; public OpenEntryCommand(MainWindowViewModel viewModel) { this.viewModel = viewModel; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return parameter is Entry; } public void Execute(object parameter) { string messageFormat = "Subject: {0}\nStart: {1}\nEnd: {2}"; Entry entry = parameter as Entry; string message = string.Format(messageFormat, entry.Subject, entry.StartDate.ToShortDateString(), entry.EndDate.ToShortDateString()); MessageBox.Show(message, "Appointment"); } } 

请帮忙,我很感激。

不幸的是,只有ButtonBase派生的控件才有可能将ICommand对象绑定到它们的Command属性(对于Click事件)。

但是,您可以使用Blend提供的API将事件(如ListBox MouseDoubleClickMouseDoubleClickICommand对象。

        

您必须定义: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"并引用System.Windows.Interactivity.dll

– 编辑 – 这是WPF4的一部分,但如果你不使用WPF4,你可以使用Microsoft.Windows.Interactivity。 这个dll来自Blend SDK,它不需要Blend,来自: http : //www.microsoft.com/downloads/en/details.aspx? FamilyID = f1ae9a30-4928-411d-970b-e682ab179e17&displaylang = en

更新 :我发现了一些可以帮到你的东西。 检查MVVM Light Toolkit上的这个链接,其中包含有关如何执行此操作的演练,以及指向所需库的链接 。 MVVM Light Toolkit是一个非常有趣的框架,用于将MVVM应用于Silverlight,WPF和WP7。

希望这可以帮助 :)

由于DoubleClick事件,这很棘手。 有几种方法可以做到这一点:

  1. 处理后面的代码中的双击事件,然后在ViewModel上手动调用命令/方法
  2. 使用附加行为将DoubleClick事件路由到您的Command
  3. 使用“混合行为” 将DoubleClick事件映射到您的命令

2和3可能更纯粹,但坦率地说,1更容易,更简单,而不是世界上最糟糕的事情。 对于一次性案例,我可能会使用方法#1。

现在,如果您更改了要求使用的每个项目的超链接,那么这将更容易。 首先命名XAML中的根元素 – 例如,对于一个Window:

  

现在,在ListBox项的DataTemplate中,使用以下内容:

     

ElementName绑定允许您从ViewModel的上下文中解析OpenEntryCmd,而不是特定的数据项。

我发现最好的方法是为我的内容创建一个简单的用户控件包装器,其中包含命令和参数的依赖项属性。

我这样做的原因是Button没有将click事件冒泡到我的ListBox,这阻止了它选择ListBoxItem。

CommandControl.xaml.cs:

 public partial class CommandControl : UserControl { public CommandControl() { MouseLeftButtonDown += OnMouseLeftButtonDown; InitializeComponent(); } private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs) { if (Command != null) { if (Command.CanExecute(CommandParameter)) { Command.Execute(CommandParameter); } } } public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None)); public ICommand Command { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } } public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandControl), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None)); public object CommandParameter { get { return (object)GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } } } 

CommandControl.xaml:

   

用法:

      

内容可以是任何内容,当单击控件时,它将执行命令。

编辑:为UserControl添加了Background="Transparent"以在控件的整个区域上启用单击事件。