ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

UWP 预约日历实战指南:基于 Windows.ApplicationModel.Appointments 命名空间的增删改查与周期预约

UWP 预约日历实战指南:基于 Windows.ApplicationModel.Appointments 命名空间的增删改查与周期预约 示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载本指南围绕 Windows-universal-samples 仓库中的 Appointments 示例展开系统讲解 UWP 应用中如何通过Windows.ApplicationModel.Appointments命名空间完成预约Appointment的定义、添加、替换、删除与时间框架展示并深入剖析AppointmentRecurrence周期规则的完整配置。读完本文你将掌握以预约 ID 字符串为枢纽的异步 API 调用范式以及参与者、忙碌状态、提醒、周期等全部属性的取值约束可直接迁移到自己的 Windows 10 UWP 日历类应用开发中。示例概览六个场景覆盖预约全生命周期该示例是微软 Windows-universal-samples 大型 UWP 功能示例集合中的一员分类为 ContactsAndCalendar其功能是演示Windows.ApplicationModel.Appointments命名空间及配套的AppointmentsProvider子命名空间。示例采用经典的 SDK 模板结构分为 C# 与 VB 两个实现版本共享同一套 XAML 界面定义C# 版本位于 Samples/Appointments/cs核心逻辑分散在Scenario1_Define.xaml.cs至Scenario6_Recurrence.xaml.cs六个页面中VB 版本位于 Samples/Appointments/vb逻辑与 C# 一一对应界面布局统一放在 Samples/Appointments/shared两个语言版本直接复用。从 SampleConfiguration.cs 的场景注册表可以看出示例的完整脉络场景类名功能Define an AppointmentScenario1_Define创建并校验一个完整的Appointment对象不落盘Add an AppointmentScenario2_Add通过默认预约提供程序应用把预约写入用户日历Replace an AppointmentScenario3_Replace依据预约 ID 替换既有预约Remove an AppointmentScenario4_Remove依据预约 ID 删除预约Show Time FrameScenario5_Show在指定时间段打开系统日历视图Recurring AppointmentsScenario6_Recurrence构建并校验周期预约规则AppointmentRecurrence示例的所有交互入口都只是调用系统预约提供程序预约数据并不保存在你的应用内而是由用户设备上的日历应用托管——这正是该命名空间的设计核心。核心概念预约 ID 字符串是增删改的枢纽原文档明确指出一个关键模型预约 IDAppointment ID是一个String对象它代表一条预约记录。整个操作流程围绕该 ID 展开调用AppointmentManager.ShowAddAppointmentAsync获得新添加预约的 ID把该 ID 连同预约数据一起保存在应用数据中官方建议使用漫游roamed应用数据以便跨设备同步之后无论替换还是删除都把这个 ID 作为参数传给ShowReplaceAppointmentAsync或ShowRemoveAppointmentAsync。三个核心 API 的签名与行为差异如下API返回值空返回值含义ShowAddAppointmentAsync(appointment, rect, placement)新预约的 IDString用户在完成添加前取消了操作ShowReplaceAppointmentAsync(appointmentId, appointment, rect, placement[, instanceStartDate])更新后的预约 IDString预约未被替换可能因 ID 无效或用户取消ShowRemoveAppointmentAsync(appointmentId, rect, placement[, instanceStartDate])是否删除成功Boolean返回false表示未删除rect参数用于定位系统弹出 UI 的锚点示例通过 SampleConfiguration.cs 中的GetElementRect辅助函数把触发按钮的FrameworkElement转换为根坐标系的Rectpublic static Rect GetElementRect(Windows.UI.Xaml.FrameworkElement element) { Windows.UI.Xaml.Media.GeneralTransform transform element.TransformToVisual(null); Point point transform.TransformPoint(new Point()); return new Rect(point, new Size(element.ActualWidth, element.ActualHeight)); }Placement.Default则让系统自行决定弹出菜单的方位。场景一定义 Appointment 对象与全部属性校验Scenario1_Define.xaml.cs 演示如何从零构造一个Appointment实例并逐一赋值。注意该场景不会保存预约——界面上明确提示appointment is not saved, so it will not show up in an appointment calendar它只用来验证属性的合法性这使它可以作为字段规则速查表使用。时间与基本信息StartTime使用DateTimeOffset构造示例代码把DatePicker的日期、TimePicker的时间和本地时区偏移拼装成完整时刻var date StartTimeDatePicker.Date; var time StartTimeTimePicker.Time; var timeZoneOffset TimeZoneInfo.Local.GetUtcOffset(DateTime.Now); var startTime new DateTimeOffset(date.Year, date.Month, date.Day, time.Hours, time.Minutes, 0, timeZoneOffset); appointment.StartTime startTime;Duration从界面下拉框取值30 分钟或 1 小时TimeSpan.FromMinutes(30)/TimeSpan.FromHours(1)。AllDay是布尔值表示全天预约。字段长度上限源码中显式校验示例对每个字符串字段都做了长度校验这些上限即该 API 的硬约束可直接作为开发时的参考属性最大长度源码校验位置Subject255 字符Scenario1_Define.xaml.csLocation32,768 字符同文件 L56-L59Details1,073,741,823 字符同文件 L64-L67Organizer.DisplayName256 字符同文件 L154-L157Organizer.Address/Invitee.Address321 字符且不能为空同文件 L163-L170Invitee.DisplayName256 字符同文件 L187-L190Uri属性接收System.Uri解析失败会抛出异常并被捕获为错误消息因此设置前务必先try/catch校验。枚举取值一览BusyStatus忙碌状态Busy、Tentative、Free、OutOfOffice、WorkingElsewhereSensitivity敏感度Public、Private参与人角色AppointmentParticipantRoleRequiredAttendee必需与会者、OptionalAttendee可选与会者、Resource资源参与人响应AppointmentParticipantResponseNone、Tentative、Accepted、Declined、Unknown。组织者与受邀者的互斥规则这是一个容易踩坑的业务规则一个预约要么有 Organizer组织者要么有 Invitees受邀者二者互斥。源码注释明确说明Organizer can only be set if there are no invitees added to this appointment.对应到 UI 上Scenario1_Define.xaml 用同一组名的两个 RadioButton 控制选中Has an Organizer?时显示组织者面板、隐藏受邀者面板反之亦然见 Scenario1_Define.xaml.cs 的Checked事件处理器。构造时若需添加多名受邀者可循环创建AppointmentInvitee实例并appointment.Invitees.Add(invitee)。场景二添加预约 ShowAddAppointmentAsyncScenario2_Add.xaml.cs 是完整的最小可用代码。整个流程只有三步创建Appointment→ 调用异步 API → 处理返回的 ID。private async void Add_Click(object sender, RoutedEventArgs e) { var appointment new Windows.ApplicationModel.Appointments.Appointment(); var rect MainPage.GetElementRect(sender as FrameworkElement); String appointmentId await Windows.ApplicationModel.Appointments.AppointmentManager .ShowAddAppointmentAsync(appointment, rect, Windows.UI.Popups.Placement.Default); if (appointmentId ! String.Empty) { rootPage.NotifyUser(Appointment Id: appointmentId, NotifyType.StatusMessage); } else { rootPage.NotifyUser(Appointment not added., NotifyType.ErrorMessage); } }需要强调两点工程实践ID 必须持久化示例注释要求把返回的appointmentId存入应用数据并做漫游否则后续无法替换或删除这条预约空字符串即用户取消只要返回值不是String.Empty就代表预约已成功写入用户的默认日历应用系统会自动拉起该应用完成添加交互。界面层面Scenario2_Add.xaml 只有一个按钮和一个描述文本无任何输入控件——因为具体数据由用户在系统日历 UI 中填写。场景三替换预约 ShowReplaceAppointmentAsyncScenario3_Replace.xaml.cs 展示了两类替换语义替换整个系列series不传instanceStartDate参数适用于一次性预约或周期预约的整条系列替换单个实例instance传入instanceStartDateDateTimeOffset系统只替换该日期开始的特定一次发生。String updatedAppointmentId; if (InstanceStartDateCheckBox.IsChecked.Value) { var instanceStartDate InstanceStartDateDatePicker.Date; updatedAppointmentId await AppointmentManager.ShowReplaceAppointmentAsync( appointmentIdOfAppointmentToReplace, appointment, rect, Windows.UI.Popups.Placement.Default, instanceStartDate); } else { updatedAppointmentId await AppointmentManager.ShowReplaceAppointmentAsync( appointmentIdOfAppointmentToReplace, appointment, rect, Windows.UI.Popups.Placement.Default); }两个细节值得注意传入的Appointment必须包含全部属性——源码注释强调 should contain all of the Appointments properties including those that may have changed即替换不是增量补丁而是整体覆盖返回的 ID 可能变化更新后的updatedAppointmentId不一定与原 ID 相同因此同样需要把新 ID 存回应用数据。场景四删除预约 ShowRemoveAppointmentAsyncScenario4_Remove.xaml.cs 的流程与替换高度对称先校验 ID 非空String.IsNullOrEmpty再按是否指定实例开始日期选择重载最后依据布尔返回值提示结果bool removed; if (InstanceStartDateCheckBox.IsChecked.Value) { var instanceStartDate InstanceStartDateDatePicker.Date; removed await AppointmentManager.ShowRemoveAppointmentAsync( appointmentId, rect, Windows.UI.Popups.Placement.Default, instanceStartDate); } else { removed await AppointmentManager.ShowRemoveAppointmentAsync( appointmentId, rect, Windows.UI.Popups.Placement.Default); } if (removed) { rootPage.NotifyUser(Appointment removed, NotifyType.StatusMessage); } else { rootPage.NotifyUser(Appointment not removed, NotifyType.ErrorMessage); }同样地带instanceStartDate的重载只删除周期预约中的某一次实例不带该参数的重载删除整个系列。场景五展示时间框架 ShowTimeFrameAsync除了对单条预约的操作AppointmentManager还提供时间维度的视图导航能力。Scenario5_Show.xaml.cs 演示在当前时间 24 小时这个时刻打开默认预约提供程序并高亮 1 小时的时段var dateToShow DateTime.Now.AddDays(1); var duration TimeSpan.FromHours(1); await Windows.ApplicationModel.Appointments.AppointmentManager.ShowTimeFrameAsync(dateToShow, duration);该 API 不涉及预约 ID用途是让用户快速查看某时间段内的日程安排适合跳转到某一天之类的导航功能。场景六构建周期预约 AppointmentRecurrenceScenario6_Recurrence.xaml.cs 深入展示AppointmentRecurrence的完整属性集。与场景一相同它只负责构造与校验不写入日历。周期对象最终通过appointment.Recurrence recurrence挂到Appointment上使用。周期单位 Unit枚举值含义Daily每天Weekly每周Monthly每月按月内日期MonthlyOnDay每月某日按月内星期几Yearly每年YearlyOnDay每年某日按年内星期几终止条件Occurrences 与 Until 互斥源码注释明确 Occurrences and Until properties are mutually exclusiveOccurrencesuint固定发生次数示例中 Slider 范围 0–10与UntilDateTimeOffset截止日期只能二选一UI 上同样用同一组名的 RadioButton 保证。周期间隔与星期几Intervaluint表示间隔倍数——界面上的例子很直观An interval of 2 for the daily unit is every other day每天单位下间隔 2 即隔天一次。DaysOfWeek是一个按位或|累积的位掩码七个 CheckBox 对应AppointmentDaysOfWeek.Sunday到.Saturdayif (SundayCheckBox.IsChecked.Value) { recurrence.DaysOfWeek | AppointmentDaysOfWeek.Sunday; } if (MondayCheckBox.IsChecked.Value) { recurrence.DaysOfWeek | AppointmentDaysOfWeek.Monday; } // ... 依此类推关键校验规则当Unit为Weekly、MonthlyOnDay或YearlyOnDay时至少必须指定一天否则视为无效周期——源码 L108-L114 显式检查DaysOfWeek AppointmentDaysOfWeek.None并报错。这个约束对应 XAML 中的复选框组Scenario6_Recurrence.xaml。其余定位属性WeekOfMonthFirst、Second、Third、Fourth、Last月内第几周配合MonthlyOnDay/YearlyOnDay使用Monthuint与Dayuint分别指定月份Slider 0–12与月内日期Slider 0–31用于Yearly/YearlyOnDay等单位的定位。构建与运行原文档给出该示例的标准构建步骤适用于整个示例集合中任意一个样例解压完整归档若通过 ZIP 获取代码务必解压整个压缩包而不只是目标样例文件夹因为所有样例依赖根目录下的 SharedContent 共享依赖打开解决方案启动 Visual Studio选择File → Open → Project/Solution进入解压目录的Samples子目录找到Appointments文件夹再进入cs或vb子目录双击其中的.sln文件本示例不含 C 版本原文档中C、C# 或 JavaScript的表述仅适用于整个集合的其他样例编译按CtrlShiftB或选择Build → Build Solution仅部署选择Build → Deploy Solution部署并运行按F5或Debug → Start Debugging带调试运行按CtrlF5或Debug → Start Without Debugging免调试运行。环境要求客户端与手机端均为 Windows 10服务器端为 Windows Server 2016 Technical Preview。清单文件 Package.appxmanifest 显示目标设备族为Windows.Universal最低版本10.0.10240.0最高测试版本10.0.22621.0唯一声明的能力是internetClient——也就是说操作本地预约日历并不需要额外的系统能力声明。相关 API 参考示例涉及的核心 API 均位于Windows.ApplicationModel.Appointments命名空间替换与删除场景还间接关联Windows.ApplicationModel.Appointments.AppointmentsProvider子命名空间系统预约提供程序的应用协议侧。动手实现时可对照以下清单查阅完整文档Appointment及AppointmentOrganizer、AppointmentInviteeAppointmentRecurrence及AppointmentRecurrenceUnit、AppointmentDaysOfWeek、AppointmentWeekOfMonthAppointmentManager.ShowAddAppointmentAsync/ShowReplaceAppointmentAsync/ShowRemoveAppointmentAsync/ShowTimeFrameAsync辅助枚举AppointmentBusyStatus、AppointmentSensitivity、AppointmentParticipantRole、AppointmentParticipantResponse在 Windows-universal-samples 仓库中除本示例外还有大量基于相同SDK 模板 多语言 共享 XAML结构的样例根目录 README.md 说明了整个集合的组织方式与共享依赖SharedContent的用法本文引用的 Appointments 示例文档 也是仓库内唯一与该命名空间直接对应的官方说明。若需进一步了解预约的完整管理模型包括周期展开、提醒触发时机等建议结合你实际使用的 Windows SDK 版本查阅对应版本文档。赞分享示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载相关推荐HelixDB快速上手指南从零开始搭建图向量数据库HelixDB快速上手指南从零开始搭建图向量数据库 HelixDB是一款基于Rust构建的开源图向量数据库专为AI应用和RAG检索增强生成系统设计。这款数据库图数据库向量数据库AI 应用RAGLark 飞书 CLI 日历 Skill预约/改约日程与会议室搜索的完整工作流指南Lark 飞书 CLI 日历 Skill预约/改约日程与会议室搜索的完整工作流指南 本文以 skills/lark calendar/references/lCLIAI 技能gws CLI 实战用 Calendar freebusy 查询跨日历空闲时段并自动预约会议gws CLI 实战用 Calendar freebusy 查询跨日历空闲时段并自动预约会议 本指南围绕仓库中的 recipe find free time创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表