这些都是很好的建议,但如果我是你,我会在你的视图模型中这样做。在您的视图模型中,您可以创建一个中继命令,然后您可以将其绑定到项目模板中的单击事件。要确定是否选择了相同的项目,您可以在视图模型中存储对所选项目的引用。我喜欢使用 MVVM Light 来处理绑定。这使您的项目将来更容易修改,并允许您在 Blend 中设置绑定。
一切都说完了,您的 XAML 将看起来像 Sergey 建议的那样。我会避免在您的视图中使用后面的代码。我将避免在此答案中编写代码,因为那里有大量示例。
这是一个:
如何将 RelayCommand 与 MVVM Light 框架一起使用
如果您需要示例,请发表评论,我会添加一个。
~干杯
我说我不打算做一个例子,但我是。干得好。
在您的项目中,仅添加 MVVM Light Libraries。
为您的视图创建一个类。一般来说,每个视图都有一个视图模型(视图:MainWindow.xaml && viewModel: MainWindowViewModel.cs)
这是非常非常基本的视图模型的代码:
所有包含的命名空间(如果它们出现在这里,我假设您已经添加了对它们的引用。MVVM Light 在 Nuget 中)
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
现在添加一个基本的公共类:
/// <summary>
/// Very basic model for example
/// </summary>
public class BasicModel
{
public string Id { get; set; }
public string Text { get; set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="text"></param>
public BasicModel(string text)
{
this.Id = Guid.NewGuid().ToString();
this.Text = text;
}
}
现在创建您的视图模型:
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
ModelsCollection = new ObservableCollection<BasicModel>(new List<BasicModel>() {
new BasicModel("Model one")
, new BasicModel("Model two")
, new BasicModel("Model three")
});
}
private BasicModel _selectedBasicModel;
/// <summary>
/// Stores the selected mode.
/// </summary>
/// <remarks>This is just an example, may be different.</remarks>
public BasicModel SelectedBasicModel
{
get { return _selectedBasicModel; }
set { Set(() => SelectedBasicModel, ref _selectedBasicModel, value); }
}
private ObservableCollection<BasicModel> _modelsCollection;
/// <summary>
/// List to bind to
/// </summary>
public ObservableCollection<BasicModel> ModelsCollection
{
get { return _modelsCollection; }
set { Set(() => ModelsCollection, ref _modelsCollection, value); }
}
}
在您的视图模型中,添加一个中继命令。请注意,我做了这个异步并让它传递了一个参数。
private RelayCommand<string> _selectItemRelayCommand;
/// <summary>
/// Relay command associated with the selection of an item in the observablecollection
/// </summary>
public RelayCommand<string> SelectItemRelayCommand
{
get
{
if (_selectItemRelayCommand == null)
{
_selectItemRelayCommand = new RelayCommand<string>(async (id) =>
{
await selectItem(id);
});
}
return _selectItemRelayCommand;
}
set { _selectItemRelayCommand = value; }
}
/// <summary>
/// I went with async in case you sub is a long task, and you don't want to lock you UI
/// </summary>
/// <returns></returns>
private async Task<int> selectItem(string id)
{
this.SelectedBasicModel = ModelsCollection.FirstOrDefault(x => x.Id == id);
Console.WriteLine(String.Concat("You just clicked:", SelectedBasicModel.Text));
//Do async work
return await Task.FromResult(1);
}
在您查看的代码中,为您的视图模型创建一个属性并将您的视图的数据上下文设置为视图模型(请注意,还有其他方法可以做到这一点,但我试图将其作为一个简单的示例。)
public partial class MainWindow : Window
{
public MainWindowViewModel MyViewModel { get; set; }
public MainWindow()
{
InitializeComponent();
MyViewModel = new MainWindowViewModel();
this.DataContext = MyViewModel;
}
}
在您的 XAML 中,您需要在代码顶部添加一些命名空间
<Window x:Class="Basic_Binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:Custom="clr-namespace:GalaSoft.MvvmLight;assembly=GalaSoft.MvvmLight"
Title="MainWindow" Height="350" Width="525">
我添加了“我”和“自定义”。
这是列表视图:
<ListView
Grid.Row="0"
Grid.Column="0"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding ModelsCollection}"
ItemTemplate="{DynamicResource BasicModelDataTemplate}">
</ListView>
这是 ListView 的 ItemTemplate:
<DataTemplate x:Key="BasicModelDataTemplate">
<Grid>
<TextBlock Text="{Binding Text}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction
Command="{Binding DataContext.SelectItemRelayCommand,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding Id}">
</i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</Grid>
</DataTemplate>
运行您的应用程序,然后查看输出窗口。您可以使用转换器来处理所选项目的样式。
这可能看起来很复杂,但是当您需要将视图与 ViewModel 分开时(例如,为多个平台开发 ViewModel),它会使生活变得更加轻松。此外,它还使在 Blend 10x 中的工作变得更加容易。一旦你开发了你的 ViewModel,你就可以把它交给一个可以让它看起来很有艺术感的设计师 :)。MVVM Light 添加了一些功能以使 Blend 识别您的 ViewModel。在大多数情况下,您可以在 ViewModel 中执行几乎所有您想要影响视图的操作。
如果有人读到这篇文章,我希望你觉得这很有帮助。如果您有任何问题,请告诉我。我在这个例子中使用了 MVVM Light,但是你可以在没有 MVVM Light 的情况下做到这一点。