WPF MVVM中点击ListView项能否调用ViewModel方法?经典库实现
实现WPF ListView点击项直接调用ViewModel方法的方案
下面提供几种经典实现方式,无需复杂第三方依赖:
方法一:利用SelectedAsset属性Setter触发逻辑
这是最直接的无依赖方案,在SelectedAsset的setter中直接调用跳转逻辑:
修改HomeViewModel代码
public class HomeViewModel { private AssetOverview _selectedAsset; public AssetOverview SelectedAsset { get => _selectedAsset; set { if (_selectedAsset == value) return; _selectedAsset = value; RaisePropertyChanged(nameof(SelectedAsset)); // 选中项变化时调用详情页跳转方法 if (_selectedAsset != null) NavigateToAssetDetail(_selectedAsset); } } // 新增详情页跳转方法 private void NavigateToAssetDetail(AssetOverview asset) { // 这里编写跳转到详情页的逻辑,例如: // var detailVM = new AssetDetailViewModel(asset); // 执行导航操作(根据你的框架实现,如RegionManager或Window跳转) } // 以下为原有代码,修正笔误并保留逻辑 private ObservableCollection<AssetOverview> _assets; public ObservableCollection<AssetOverview> Assets { get => _assets; set { if (_assets == value) return; _assets = value; RaisePropertyChanged(nameof(Assets)); // 修正原代码中"MyAssets"的笔误 } } private static HttpClient _client; public event PropertyChangedEventHandler PropertyChanged; public HomeViewModel() { Assets = new ObservableCollection<AssetOverview>(); try { _client = new HttpClient(); _client.DefaultRequestHeaders.Accept.Clear(); _client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); } catch { } PopulateCollection(); } async void PopulateCollection() { var client = new RestClient(); var request = new RestRequest("https://cryptingup.com/api/assetsoverview"); request.AddHeader("Accept", "application/json"); request.AddHeader("Content-Type", "application/json"); var response = client.GetAsync(request).GetAwaiter().GetResult(); var date = JsonConvert.DeserializeObject<CurrencyModelOverview>(response.Content); for (int i = 0; Assets.Count < 10; i++) { if (!string.IsNullOrEmpty(date.Assets[i].Name)) { Assets.Add(date.Assets[i]); } } } private void RaisePropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
方法二:使用Microsoft.Xaml.Behaviors.Wpf库绑定事件转Command
这是WPF生态中经典的事件转Command方案,依赖官方维护的行为库:
步骤1:安装NuGet包
在项目中安装Microsoft.Xaml.Behaviors.Wpf
步骤2:修改XAML代码
<!-- 先在根节点添加命名空间 --> xmlns:b="http://schemas.microsoft.com/xaml/behaviors" <ListView Background="#222222" SelectedItem="{Binding SelectedAsset}" ScrollViewer.CanContentScroll="False" ItemsSource="{Binding Assets}" Style="{StaticResource ListStyle}"> <b:Interaction.Triggers> <b:EventTrigger EventName="SelectionChanged"> <b:InvokeCommandAction Command="{Binding NavigateToDetailCommand}" CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=ListView}}"/> </b:EventTrigger> </b:Interaction.Triggers> </ListView>
步骤3:在HomeViewModel中添加Command
先实现基础的RelayCommand(如果没有现成实现):
public class RelayCommand : ICommand { private readonly Action<object> _execute; private readonly Func<object, bool> _canExecute; public event EventHandler CanExecuteChanged; public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public bool CanExecute(object parameter) { return _canExecute?.Invoke(parameter) ?? true; } public void Execute(object parameter) { _execute(parameter); } public void RaiseCanExecuteChanged() { CanExecuteChanged?.Invoke(this, EventArgs.Empty); } }
然后在HomeViewModel中添加Command和对应方法:
public class HomeViewModel { public AssetOverview SelectedAsset { get; set; } // 新增跳转Command public ICommand NavigateToDetailCommand { get; } public HomeViewModel() { // 初始化Command NavigateToDetailCommand = new RelayCommand(NavigateToAssetDetail); // 原有初始化代码 Assets = new ObservableCollection<AssetOverview>(); try { _client = new HttpClient(); _client.DefaultRequestHeaders.Accept.Clear(); _client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue("application/json")); } catch { } PopulateCollection(); } private void NavigateToAssetDetail(object parameter) { var asset = parameter as AssetOverview; if (asset == null) return; // 执行详情页跳转逻辑 } // 原有代码保持不变... }
方法三:View后台绑定SelectionChanged事件
如果不想引入库,也可以在View后台代码中直接绑定事件:
View后台代码(如HomeWindow.xaml.cs)
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (DataContext is HomeViewModel vm) { var selectedAsset = (sender as ListView)?.SelectedItem as AssetOverview; if (selectedAsset != null) vm.NavigateToAssetDetail(selectedAsset); } }
XAML中添加事件绑定
<ListView Background="#222222" SelectedItem="{Binding SelectedAsset}" ScrollViewer.CanContentScroll="False" ItemsSource="{Binding Assets}" Style="{StaticResource ListStyle}" SelectionChanged="ListView_SelectionChanged"> </ListView>
内容的提问来源于stack exchange,提问作者Palamar66
相关产品推荐
相关产品推荐

