.NET MAUI中如何将API返回的Events数据转为SfScheduler预约数据?
问题
首次在面向安卓、iOS和Windows的.NET MAUI应用中使用SyncFusion SfScheduler,硬编码的SchedulerAppointment数据能正常绑定到调度器,但不清楚如何高效地将API返回的ObservableCollection<Events>转换为SchedulerAppointment集合,不想手动遍历,寻求更优实现方式。
现有代码
XAML代码
<scheduler:SfScheduler x:Name="calendar" View="Month" FirstDayOfWeek="Monday" AllowedViews="Week ,Month" TodayHighlightBrush="Gray" AppointmentsSource="{Binding SchedulerEvents}" Tapped="calendar_Tapped" > <scheduler:SfScheduler.MonthView> <scheduler:SchedulerMonthView AppointmentDisplayMode="Indicator" /> </scheduler:SfScheduler.MonthView> <scheduler:SfScheduler.BindingContext > <local:SchedulerControlViewModel> </local:SchedulerControlViewModel> </scheduler:SfScheduler.BindingContext> </scheduler:SfScheduler>
ViewModel代码
using Syncfusion.Maui.Scheduler; using System.Collections.ObjectModel; namespace MyGolfSociety.ViewModels { public class SchedulerControlViewModel { public ObservableCollection<SchedulerAppointment> SchedulerEvents { get; set; } public SchedulerControlViewModel() { this.SchedulerEvents = new ObservableCollection<SchedulerAppointment> { new SchedulerAppointment { StartTime = new DateTime(2023, 8, 5,00,01,01), EndTime = new DateTime(2023, 8, 5,23,01,01), Subject = "TEST Appointment", IsAllDay = true } }; } } }
Events模型代码
namespace MyGolfSociety.Models { public class Events { public int EventId { get; set; } public string? EventName { get; set; } public DateTime EventDateStart { get; set; } public DateTime? EventDateEnd { get; set; } public int? CourseId { get; set; } } }
解决方案
方案1:利用SyncFusion内置数据映射(最优解)
SyncFusion SfScheduler支持直接绑定自定义实体类,无需手动转换集合。通过SchedulerAppointmentMapping配置字段映射即可实现绑定:
修改XAML
添加字段映射配置:
<scheduler:SfScheduler x:Name="calendar" View="Month" FirstDayOfWeek="Monday" AllowedViews="Week ,Month" TodayHighlightBrush="Gray" AppointmentsSource="{Binding ApiEvents}" Tapped="calendar_Tapped" > <!-- 配置实体与SchedulerAppointment的字段映射 --> <scheduler:SfScheduler.AppointmentMapping> <scheduler:SchedulerAppointmentMapping StartTime="EventDateStart" EndTime="EventDateEnd" Subject="EventName" IsAllDay="True" /> <!-- 或根据业务逻辑绑定到ViewModel属性 --> </scheduler:SfScheduler.AppointmentMapping> <scheduler:SfScheduler.MonthView> <scheduler:SchedulerMonthView AppointmentDisplayMode="Indicator" /> </scheduler:SfScheduler.MonthView> <scheduler:SfScheduler.BindingContext > <local:SchedulerControlViewModel> </local:SchedulerControlViewModel> </scheduler:SfScheduler.BindingContext> </scheduler:SfScheduler>
修改ViewModel
直接持有API返回的ObservableCollection<Events>:
using Syncfusion.Maui.Scheduler; using System.Collections.ObjectModel; using MyGolfSociety.Models; namespace MyGolfSociety.ViewModels { public class SchedulerControlViewModel { public ObservableCollection<Events> ApiEvents { get; set; } public SchedulerControlViewModel() { // 模拟API返回数据 ApiEvents = new ObservableCollection<Events> { new Events { EventId = 1, EventName = "高尔夫赛事", EventDateStart = new DateTime(2023, 8, 5), EventDateEnd = new DateTime(2023, 8, 5, 23, 59, 59), CourseId = 101 } }; } // 实际场景中从API加载数据的方法 public async Task LoadEventsFromApi() { var apiResponse = await YourApiService.GetEventsAsync(); ApiEvents = new ObservableCollection<Events>(apiResponse); } } }
方案2:LINQ+扩展方法批量转换
如果必须转换为SchedulerAppointment集合,可通过LINQ结合扩展方法实现高效转换:
添加扩展方法
using Syncfusion.Maui.Scheduler; using MyGolfSociety.Models; namespace MyGolfSociety.Extensions { public static class EventExtensions { public static SchedulerAppointment ToSchedulerAppointment(this Events @event) { return new SchedulerAppointment { StartTime = @event.EventDateStart, EndTime = @event.EventDateEnd ?? @event.EventDateStart.AddDays(1), // 处理结束时间为空的情况 Subject = @event.EventName ?? "未命名活动", IsAllDay = true // 根据业务需求调整 }; } } }
在ViewModel中执行转换
using Syncfusion.Maui.Scheduler; using System.Collections.ObjectModel; using System.Linq; using MyGolfSociety.Models; using MyGolfSociety.Extensions; namespace MyGolfSociety.ViewModels { public class SchedulerControlViewModel { public ObservableCollection<SchedulerAppointment> SchedulerEvents { get; set; } public SchedulerControlViewModel() { // 模拟API数据转换 var apiEvents = new ObservableCollection<Events> { new Events { EventId = 1, EventName = "高尔夫赛事", EventDateStart = new DateTime(2023, 8, 5), EventDateEnd = new DateTime(2023, 8, 5, 23, 59, 59) } }; // LINQ批量转换 SchedulerEvents = new ObservableCollection<SchedulerAppointment>( apiEvents.Select(e => e.ToSchedulerAppointment()) ); } // 实际API加载转换逻辑 public async Task LoadAndConvertEvents() { var apiResponse = await YourApiService.GetEventsAsync(); SchedulerEvents = new ObservableCollection<SchedulerAppointment>( apiResponse.Select(e => e.ToSchedulerAppointment()) ); } } }
方案3:AutoMapper自动映射
若项目已使用AutoMapper,可配置映射规则实现一键转换:
配置映射规则
using AutoMapper; using Syncfusion.Maui.Scheduler; using MyGolfSociety.Models; namespace MyGolfSociety.Mappings { public class EventProfile : Profile { public EventProfile() { CreateMap<Events, SchedulerAppointment>() .ForMember(dest => dest.StartTime, opt => opt.MapFrom(src => src.EventDateStart)) .ForMember(dest => dest.EndTime, opt => opt.MapFrom(src => src.EventDateEnd ?? src.EventDateStart.AddDays(1))) .ForMember(dest => dest.Subject, opt => opt.MapFrom(src => src.EventName ?? "未命名活动")) .ForMember(dest => dest.IsAllDay, opt => opt.MapFrom(src => true)); } } }
在ViewModel中使用
using Syncfusion.Maui.Scheduler; using AutoMapper; using System.Collections.ObjectModel; using MyGolfSociety.Models; namespace MyGolfSociety.ViewModels { public class SchedulerControlViewModel { private readonly IMapper _mapper; public ObservableCollection<SchedulerAppointment> SchedulerEvents { get; set; } public SchedulerControlViewModel(IMapper mapper) { _mapper = mapper; LoadEvents(); } private async void LoadEvents() { var apiEvents = await YourApiService.GetEventsAsync(); var schedulerAppointments = _mapper.Map<List<SchedulerAppointment>>(apiEvents); SchedulerEvents = new ObservableCollection<SchedulerAppointment>(schedulerAppointments); } } }
内容的提问来源于stack exchange,提问作者Chris Smith
相关产品推荐
相关产品推荐

