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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 20:07:15