You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:01:19