C#类交互通信:API服务、模型与MVVM视图模型联动问题
问题分析与修正方案
核心错误点
- ViewModel未正确关联API服务:构造函数中创建了
ApiServiceListUser实例,但未赋值给私有字段client,后续无法调用API获取数据;且没有触发数据加载逻辑。 - 未执行数据加载与转换:从未调用
RefreshDataAsync方法拉取数据,也未将API返回的List<Meetman>转换为ObservableCollection<Meetman>赋值给绑定属性。 - API服务的静态成员风险:
HttpClient和JsonSerializerOptions用static修饰,会导致所有服务实例共享同一客户端,可能引发并发冲突或资源泄漏。
修正后的组件实现
1. 修正API服务类ApiServiceListUser
移除静态修饰符,确保每个服务实例拥有独立的客户端(或推荐将HttpClient注册为单例服务,避免重复创建):
public class ApiServiceListUser { private readonly HttpClient _client; private readonly JsonSerializerOptions _options; public ApiServiceListUser() { _client = new HttpClient(); _options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true, }; } public async Task<List<Meetman>?> RefreshDataAsync() { List<Meetman>? meetmans = null; Uri uri = new("http://10.0.2.2:5000/api/meetman/getall"); try { HttpResponseMessage response = await _client.GetAsync(uri); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); meetmans = JsonSerializer.Deserialize<List<Meetman>>(content, _options); } } catch (Exception ex) { Debug.WriteLine(@"\tERROR {0}", ex.Message); } return meetmans; } }
2. 修正视图模型VMMeetman
使用依赖注入获取API服务实例,添加异步命令触发数据加载,并将API返回的列表转换为ObservableCollection:
using CommunityToolkit.Mvvm.Input; public partial class VMMeetman : ObservableObject { private readonly ApiServiceListUser _apiService; // 构造函数注入API服务(需先将ApiServiceListUser注册为服务) public VMMeetman(ApiServiceListUser apiService) { _apiService = apiService; Meetmans = new ObservableCollection<Meetman>(); // 页面加载时自动触发数据刷新 Task.Run(LoadMeetmansAsync); } [ObservableProperty] private ObservableCollection<Meetman> _meetmans; [ObservableProperty] private int _meetmanId; [ObservableProperty] private string _iname = string.Empty; [ObservableProperty] private string _sname = string.Empty; [ObservableProperty] private string _tname = string.Empty; [ObservableProperty] private string _location = string.Empty; // 异步命令,用于手动触发刷新(比如下拉刷新) [RelayCommand] private async Task LoadMeetmansAsync() { var fetchedMeetmans = await _apiService.RefreshDataAsync(); if (fetchedMeetmans != null) { Meetmans.Clear(); foreach (var meetman in fetchedMeetmans) { Meetmans.Add(meetman); } } } }
3. 服务注册与View绑定
- 服务注册:在应用启动时,将API服务和视图模型注册为依赖注入服务(以MAUI为例):
// 在MauiProgram.cs中 builder.Services.AddSingleton<ApiServiceListUser>(); builder.Services.AddTransient<VMMeetman>();
- View绑定:在页面的XAML中设置BindingContext,并绑定CarouselView的ItemsSource:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:vm="clr-namespace:你的命名空间" x:Class="你的页面类"> <ContentPage.BindingContext> <vm:VMMeetman /> <!-- 或通过依赖注入获取:BindingContext="{Binding Source={StaticResource VMMeetman}}" --> </ContentPage.BindingContext> <CarouselView ItemsSource="{Binding Meetmans}"> <CarouselView.ItemTemplate> <DataTemplate> <!-- 这里绑定Meetman的属性,比如 --> <Label Text="{Binding Iname}" /> <Label Text="{Binding Sname}" /> </DataTemplate> </CarouselView.ItemTemplate> </CarouselView> </ContentPage>
组件关联逻辑
- API服务:负责与后端交互,发送HTTP请求并将JSON响应反序列化为
Meetman模型列表。 - 视图模型:持有API服务实例,调用其方法获取数据,转换为
ObservableCollection(支持UI自动更新),并暴露给View绑定的属性。 - View:通过BindingContext绑定到视图模型,将CarouselView的ItemsSource绑定到
Meetmans属性,实现数据展示。
内容的提问来源于stack exchange,提问作者Артур Дементьев
相关产品推荐
相关产品推荐

