使用 Microsoft Graph 生成 UWP 应用
本教程指导你如何生成使用 Microsoft Graph API 检索用户的日历信息的通用 Windows 平台 (UWP) 应用。
提示
如果只想下载已完成的教程,可以下载或克隆GitHub存储库。
先决条件
在开始本教程之前,应该先在Visual Studio开发人员模式Windows 10的计算机上安装此软件。 如果尚未安装Visual Studio,请访问上一链接,查看下载选项。
您还应该有一个在 Outlook.com 上拥有邮箱的个人 Microsoft 帐户,或者一个 Microsoft 工作或学校帐户。 如果你没有 Microsoft 帐户,则有几个选项可以获取免费帐户:
- 你可以 注册新的个人 Microsoft 帐户。
- 你可以注册开发人员计划Microsoft 365免费订阅Microsoft 365订阅。
备注
本教程是使用 Visual Studio 2019 版本 16.8.3 编写的。 本指南中的步骤可能与其他版本一起运行,但该版本尚未经过测试。
反馈
Please provide any feedback on this tutorial in the GitHub repository.
创建通用 Windows 平台应用
在此部分中,你将创建新的 UWP 应用。
打开 Visual Studio ,选择“新建一个项目”。 选择"空白应用 (通用Windows) " 选项,C#"下一步 "。

在"配置新项目"对话框中,
GraphTutorial输入"Project 名称"字段并选择"创建 "。
重要
请确保为这些实验室说明中指定的Visual Studio Project输入完全相同的名称。 Visual Studio 项目名称在代码中成为了命名空间的一部分。 在这些说明里的代码依赖于匹配在这些说明中指定的 Visual Studio 项目名称的命名空间。 如果你使用不同的项目名称,代码不会编译,除非你调整所有的命名空间来匹配你在创建项目时输入的 Visual Studio 项目名称。
选择“确定”。 在"新建通用Windows平台Project 对话框中,确保"最低版本"设置为
Windows 10, Version 1809 (10.0; Build 17763)或更高版本,然后选择"确定 "。
安装 NuGet 包
在继续之前,请安装一些NuGet包,你稍后会使用它。
- Microsoft。Toolkit。Uwp.Ui.Controls.DataGrid,用于显示 Microsoft Graph。
- Microsoft。Toolkit。Graph。用于处理登录和访问令牌检索的控件。
选择“工具 > NuGet 程序包管理器 > 程序包管理控制台”。 在“程序包管理器控制台”中,输入以下命令。
Install-Package Microsoft.Toolkit.Uwp.Ui.Controls.DataGrid -IncludePrerelease Install-Package Microsoft.Toolkit.Graph.Controls -IncludePrerelease
设计应用
在此部分中,你将为应用创建 UI。
首先添加应用程序级别变量以跟踪身份验证状态。 在"解决方案资源管理器"中,展开 App.xaml 并打开 App.xaml.cs。 将以下属性添加到
App类。public bool IsAuthenticated { get; set; }定义主页的布局。 打开
MainPage.xaml并将其全部内容替换为以下内容。<Page x:Class="GraphTutorial.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:GraphTutorial" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:providers="using:Microsoft.Toolkit.Graph.Providers" xmlns:wgt="using:Microsoft.Toolkit.Graph.Controls" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Interactivity:Interaction.Behaviors> <providers:InteractiveProviderBehavior x:Name="MsalProvider" /> </Interactivity:Interaction.Behaviors> <Grid> <NavigationView x:Name="NavView" IsSettingsVisible="False" ItemInvoked="NavView_ItemInvoked"> <NavigationView.Header> <wgt:LoginButton x:Name="Login" VerticalAlignment="Top" HorizontalAlignment="Right" /> </NavigationView.Header> <NavigationView.MenuItems> <NavigationViewItem Content="Home" x:Name="Home" Tag="home"> <NavigationViewItem.Icon> <FontIcon Glyph=""/> </NavigationViewItem.Icon> </NavigationViewItem> <NavigationViewItem Content="Calendar" x:Name="Calendar" Tag="calendar"> <NavigationViewItem.Icon> <FontIcon Glyph=""/> </NavigationViewItem.Icon> </NavigationViewItem> <NavigationViewItem Content="New event" x:Name="NewEvent" Tag="newevent"> <NavigationViewItem.Icon> <FontIcon Glyph=""/> </NavigationViewItem.Icon> </NavigationViewItem> </NavigationView.MenuItems> <StackPanel> <controls:InAppNotification x:Name="Notification" ShowDismissButton="true" /> <Frame x:Name="RootFrame" Margin="24, 0" /> </StackPanel> </NavigationView> </Grid> </Page>这将定义一个基本 NavigationView,其中 " 主页 "、" 日历"和"新建"事件导航链接充当应用的主视图。 它还在视图的标题中添加一个 LoginButton 控件。 该控件将允许用户登录和注销。该控件尚未完全启用,你将在稍后的练习中对其进行配置。
右键单击"解决方案 资源管理器"中的图形 教程项目,然后选择 ">新项目..."。 选择 "空白页",
HomePage.xaml在"名称"字段中 输入,然后选择"添加 "。 将文件中<Grid>现有的 元素替换为以下内容。<Grid> <StackPanel> <TextBlock FontSize="44" FontWeight="Bold" Margin="0, 12">Microsoft Graph UWP Tutorial</TextBlock> <TextBlock x:Name="HomePageMessage">Please sign in to continue.</TextBlock> </StackPanel> </Grid>在 "解决方案资源管理器"中展开 MainPage.xaml 并打开
MainPage.xaml.cs。 将以下函数添加到MainPage类以管理身份验证状态。private void SetAuthState(bool isAuthenticated) { (Application.Current as App).IsAuthenticated = isAuthenticated; // Toggle controls that require auth Calendar.IsEnabled = isAuthenticated; NewEvent.IsEnabled = isAuthenticated; }将以下代码添加到
MainPage()行 后的this.InitializeComponent();构造函数。// Initialize auth state to false SetAuthState(false); // Configure MSAL provider // TEMPORARY MsalProvider.ClientId = "11111111-1111-1111-1111-111111111111"; // Navigate to HomePage.xaml RootFrame.Navigate(typeof(HomePage));当应用首次启动时,它将初始化身份验证状态并
false导航到主页。添加以下事件处理程序,以在用户从导航视图中选择项目时加载请求的页面。
private void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args) { var invokedItem = args.InvokedItem as string; switch (invokedItem.ToLower()) { case "new event": throw new NotImplementedException(); break; case "calendar": throw new NotImplementedException(); break; case "home": default: RootFrame.Navigate(typeof(HomePage)); break; } }保存所有更改,然后按 F5 或选择"调试 ">"开始 Visual Studio"。
备注
请确保为计算机选择适当的配置 (ARM、x64、x86) 。

在门户中注册该应用
在此练习中,你将使用管理中心Azure Active Directory Azure AD 本机应用程序。
打开浏览器,并转到 Azure Active Directory 管理中心。然后,使用 个人帐户(亦称为“Microsoft 帐户”)或 工作或学校帐户 登录。
选择左侧导航栏中的“Azure Active Directory”,再选择“管理”下的“应用注册”。

选择“新注册”。 在“注册应用”页上,按如下方式设置值。
- 将“名称”设置为“
UWP Graph Tutorial”。 - 将“受支持的帐户类型”设置为“任何组织目录中的帐户和个人 Microsoft 帐户”。
- 在 "重定向 URI" 下,将下拉列表更改为"公共客户端 (移动&桌面) ", 将值设置为
https://login.microsoftonline.com/common/oauth2/nativeclient。

- 将“名称”设置为“
选择“注册”。 在 "UWP Graph 教程"页上,复制 Application (client) ID 的值并保存它,你将在下一步中需要该值。

添加 Azure AD 身份验证
在此练习中,你将从上一练习中扩展应用程序,以支持使用 Azure AD 进行身份验证。 这是必需的,才能获取必要的 OAuth 访问令牌来调用 Microsoft Graph。 在此步骤中,您将 LoginButton 控件从 Windows Graph 控件集成到应用程序中。
在"解决方案资源管理器"中右键单击 GraphTutorial 项目,然后选择 ">新项目..."。 Choose Resources File (.resw), name the file and select
OAuth.reswAdd. 当新文件在 Visual Studio 中打开时,请创建两个资源,如下所示。- 名称
AppId:、值 :你在应用程序注册门户中生成的应用 ID - 名称
Scopes:,值:User.Read User.ReadBasic.All People.Read MailboxSettings.Read Calendars.ReadWrite

重要
如果你使用的是源代码管理(如 git),那么现在是从源代码管理中排除文件以避免意外泄露应用
OAuth.reswID 的一个好时间。- 名称
配置 LoginButton 控件
打开
MainPage.xaml.cs并添加using以下语句到文件顶部。using Microsoft.Toolkit.Graph.Providers;将现有构造函数替换为以下内容。
public MainPage() { this.InitializeComponent(); // Load OAuth settings var oauthSettings = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView("OAuth"); var appId = oauthSettings.GetString("AppId"); var scopes = oauthSettings.GetString("Scopes"); if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(scopes)) { Notification.Show("Could not load OAuth Settings from resource file."); } else { // Configure MSAL provider MsalProvider.ClientId = appId; MsalProvider.Scopes = new ScopeSet(scopes.Split(' ')); // Handle auth state change ProviderManager.Instance.ProviderUpdated += ProviderUpdated; // Navigate to HomePage.xaml RootFrame.Navigate(typeof(HomePage)); } }此代码从 MSAL 提供程序加载设置,并初始化
OAuth.resw具有这些值的 MSAL 提供程序。现在,在 上为
ProviderUpdated事件添加事件处理程序ProviderManager。 将以下函数添加到MainPage类。private void ProviderUpdated(object sender, ProviderUpdatedEventArgs e) { var globalProvider = ProviderManager.Instance.GlobalProvider; SetAuthState(globalProvider != null && globalProvider.State == ProviderState.SignedIn); RootFrame.Navigate(typeof(HomePage)); }当提供程序更改或提供程序状态更改时,将触发此事件。
在解决方案资源管理器中,展开 HomePage.xaml 并 打开
HomePage.xaml.cs。 将现有构造函数替换为以下内容。public HomePage() { this.InitializeComponent(); if ((App.Current as App).IsAuthenticated) { HomePageMessage.Text = "Welcome! Please use the menu to the left to select a view."; } }重新启动应用,然后单击 应用 顶部的"登录"控件。 登录后,UI 应更改为指示你已成功登录。

备注
ButtonLogin该控件实现存储和刷新访问令牌的逻辑。 令牌存储在安全存储中并根据需要刷新。
获取日历视图
在此练习中,你将将 Microsoft Graph合并到应用程序中。 对于此应用程序,你将使用适用于 .NET 的 Microsoft Graph客户端库调用 Microsoft Graph。
从 Outlook 获取日历事件
为日历视图添加新页面。 在"解决方案资源管理器"中右键单击 GraphTutorial 项目,然后选择 ">新项目..."。 选择 "空白页",
CalendarPage.xaml在"名称"字段中 输入,然后选择"添加 "。打开
CalendarPage.xaml并添加现有元素中的以下<Grid>行。<TextBlock x:Name="Events" TextWrapping="Wrap"/>打开
CalendarPage.xaml.cs并添加文件using顶部的以下语句。using Microsoft.Graph; using Microsoft.Toolkit.Graph.Providers; using Microsoft.Toolkit.Uwp.UI.Controls; using Newtonsoft.Json;将以下函数添加到
CalendarPage类。private void ShowNotification(string message) { // Get the main page that contains the InAppNotification var mainPage = (Window.Current.Content as Frame).Content as MainPage; // Get the notification control var notification = mainPage.FindName("Notification") as InAppNotification; notification.Show(message); } protected override async void OnNavigatedTo(NavigationEventArgs e) { // Get the Graph client from the provider var graphClient = ProviderManager.Instance.GlobalProvider.Graph; try { // Get the user's mailbox settings to determine // their time zone var user = await graphClient.Me.Request() .Select(u => new { u.MailboxSettings }) .GetAsync(); var startOfWeek = GetUtcStartOfWeekInTimeZone(DateTime.Today, user.MailboxSettings.TimeZone); var endOfWeek = startOfWeek.AddDays(7); var queryOptions = new List<QueryOption> { new QueryOption("startDateTime", startOfWeek.ToString("o")), new QueryOption("endDateTime", endOfWeek.ToString("o")) }; // Get the events var events = await graphClient.Me.CalendarView.Request(queryOptions) .Header("Prefer", $"outlook.timezone=\"{user.MailboxSettings.TimeZone}\"") .Select(ev => new { ev.Subject, ev.Organizer, ev.Start, ev.End }) .OrderBy("start/dateTime") .Top(50) .GetAsync(); // TEMPORARY: Show the results as JSON Events.Text = JsonConvert.SerializeObject(events.CurrentPage); } catch (ServiceException ex) { ShowNotification($"Exception getting events: {ex.Message}"); } base.OnNavigatedTo(e); } private static DateTime GetUtcStartOfWeekInTimeZone(DateTime today, string timeZoneId) { TimeZoneInfo userTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); // Assumes Sunday as first day of week int diff = System.DayOfWeek.Sunday - today.DayOfWeek; // create date as unspecified kind var unspecifiedStart = DateTime.SpecifyKind(today.AddDays(diff), DateTimeKind.Unspecified); // convert to UTC return TimeZoneInfo.ConvertTimeToUtc(unspecifiedStart, userTimeZone); }请考虑中的代码
OnNavigatedTo正在执行。- 将调用的 URL 为
/me/calendarview。startDateTime和endDateTime参数定义日历视图的起始和结束。Prefer: outlook.timezone标头将导致start在用户的时区中返回事件的 和end。Select函数将每个事件返回的字段限定为应用将实际使用的字段。OrderBy函数按开始日期和时间对结果进行排序。Top函数最多请求 50 个事件。
- 将调用的 URL 为
修改
NavView_ItemInvoked文件中的方法MainPage.xaml.cs,以将现有switch语句替换为以下内容。switch (invokedItem.ToLower()) { case "new event": throw new NotImplementedException(); break; case "calendar": RootFrame.Navigate(typeof(CalendarPage)); break; case "home": default: RootFrame.Navigate(typeof(HomePage)); break; }
现在,你可以运行应用、登录并单击左侧菜单中的"日历"导航项。 你应该在用户日历上看到事件的 JSON 转储。
显示结果
将 的全部内容
CalendarPage.xaml替换为以下内容。<Page x:Class="GraphTutorial.CalendarPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:GraphTutorial" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid> <controls:DataGrid x:Name="EventList" Grid.Row="1" AutoGenerateColumns="False"> <controls:DataGrid.Columns> <controls:DataGridTextColumn Header="Organizer" Width="SizeToCells" Binding="{Binding Organizer.EmailAddress.Name}" FontSize="20" /> <controls:DataGridTextColumn Header="Subject" Width="SizeToCells" Binding="{Binding Subject}" FontSize="20" /> <controls:DataGridTextColumn Header="Start" Width="SizeToCells" Binding="{Binding Start.DateTime}" FontSize="20" /> <controls:DataGridTextColumn Header="End" Width="SizeToCells" Binding="{Binding End.DateTime}" FontSize="20" /> </controls:DataGrid.Columns> </controls:DataGrid> </Grid> </Page>打开
CalendarPage.xaml.cs并替换为Events.Text = JsonConvert.SerializeObject(events.CurrentPage);以下代码行。EventList.ItemsSource = events.CurrentPage.ToList();如果现在运行应用并选择日历,应获取数据网格中的事件列表。 但是 ,Start 和 End 值以非用户友好方式显示。 可以使用值转换器 来控制这些值 的显示方式。
在"解决方案资源管理器"中右键单击 GraphTutorial 项目,然后选择"添加>类..."。 将类命名
GraphDateTimeTimeZoneConverter.cs,然后选择"添加 "。 将文件的全部内容替换为以下内容。using Microsoft.Graph; using Microsoft.Graph.Extensions; using System; namespace GraphTutorial { class GraphDateTimeTimeZoneConverter : Windows.UI.Xaml.Data.IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { DateTimeTimeZone date = value as DateTimeTimeZone; if (date != null) { return date.ToDateTime().ToString(); } return string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } } }此代码接受 Microsoft 返回的dateTimeTimeZone Graph并解析为
DateTimeOffset对象。 然后,它将值转换为用户的时区并返回格式化的值。打开
CalendarPage.xaml,在 元素 前添加<Grid>以下内容。<Page.Resources> <local:GraphDateTimeTimeZoneConverter x:Key="DateTimeTimeZoneValueConverter" /> </Page.Resources>将最后两
DataGridTextColumn个元素替换为以下内容。<controls:DataGridTextColumn Header="Start" Width="SizeToCells" Binding="{Binding Start, Converter={StaticResource DateTimeTimeZoneValueConverter}}" FontSize="20" /> <controls:DataGridTextColumn Header="End" Width="SizeToCells" Binding="{Binding End, Converter={StaticResource DateTimeTimeZoneValueConverter}}" FontSize="20" />运行应用、登录,然后单击 "日历" 导航项。 你应该会看到格式化的 Start 和 End 值的事件列表。

创建新事件
在此部分中,您将添加在用户日历上创建事件的能力。
为新的事件视图添加新页面。 在"解决方案资源管理器"中右键单击 GraphTutorial 项目,然后选择 ">新项目..."。 选择 "空白页",
NewEventPage.xaml在"名称"字段中 输入,然后选择"添加 "。打开 NewEventPage.xaml, 并将其内容替换为以下内容。
<Page xmlns:wgt="using:Microsoft.Toolkit.Graph.Controls" x:Class="GraphTutorial.NewEventPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:GraphTutorial" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Margin="10" Spacing="10"> <TextBox Header="Subject" Text="{Binding Subject, Mode=TwoWay}" /> <TextBlock Text="Attendees"/> <wgt:PeoplePicker Name="AttendeePicker" /> <Grid ColumnSpacing="10" RowSpacing="10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <DatePicker Header="Start Date" Date="{Binding StartDate, Mode=TwoWay}" /> <TimePicker Header="Start Time" Time="{Binding StartTime, Mode=TwoWay}" Grid.Column="2" /> <DatePicker Header="End Date" Date="{Binding EndDate, Mode=TwoWay}" Grid.Row="2" /> <TimePicker Header="End Time" Time="{Binding EndTime, Mode=TwoWay}" Grid.Row="2" Grid.Column="2" /> </Grid> <TextBox Header="Body" Text="{Binding Body, Mode=TwoWay}" AcceptsReturn="True" TextWrapping="Wrap" Height="200" ScrollViewer.VerticalScrollBarVisibility="Auto" /> <Button Content="Create" Click="CreateEvent" IsEnabled="{Binding IsValid}"/> <ProgressRing Name="CreateProgress" Visibility="Collapsed" IsActive="False" /> </StackPanel> </Page>打开 NewEventPage.xaml.cs, 将以下语句
using添加到文件顶部。using System.ComponentModel; using Microsoft.Graph; using Microsoft.Graph.Extensions; using Microsoft.Toolkit.Graph.Providers; using Microsoft.Toolkit.Uwp.UI.Controls; using System.Runtime.CompilerServices;将 INotifyPropertyChange 接口添加到 NewEventPage 类。 将现有的类声明替换为以下内容。
public sealed partial class NewEventPage : Page, INotifyPropertyChanged { public NewEventPage() { this.InitializeComponent(); DataContext = this; } }将以下属性添加到 NewEventPage 类。
private TimeZoneInfo _userTimeZone = null; // Value of the Subject text box private string _subject = ""; public string Subject { get { return _subject; } set { _subject = value; OnPropertyChanged(); } } // Value of the Start date picker private DateTimeOffset _startDate = DateTimeOffset.Now; public DateTimeOffset StartDate { get { return _startDate; } set { _startDate = value; OnPropertyChanged(); } } // Value of the Start time picker private TimeSpan _startTime = TimeSpan.Zero; public TimeSpan StartTime { get { return _startTime; } set { _startTime = value; OnPropertyChanged(); } } // Value of the End date picker private DateTimeOffset _endDate = DateTimeOffset.Now; public DateTimeOffset EndDate { get { return _endDate; } set { _endDate = value; OnPropertyChanged(); } } // Value of the End time picker private TimeSpan _endTime = TimeSpan.Zero; public TimeSpan EndTime { get { return _endTime; } set { _endTime = value; OnPropertyChanged(); } } // Value of the Body text box private string _body = ""; public string Body { get { return _body; } set { _body = value; OnPropertyChanged(); } } // Combine the date from date picker with time from time picker private DateTimeOffset CombineDateAndTime(DateTimeOffset date, TimeSpan time) { // Use the year, month, and day from the supplied DateTimeOffset // to create a new DateTime at midnight var dt = new DateTime(date.Year, date.Month, date.Day); // Add the TimeSpan, and use the user's timezone offset return new DateTimeOffset(dt + time, _userTimeZone.BaseUtcOffset); } // Combined value of Start date and time pickers public DateTimeOffset Start { get { return CombineDateAndTime(StartDate, StartTime); } } // Combined value of End date and time pickers public DateTimeOffset End { get { return CombineDateAndTime(EndDate, EndTime); } } public bool IsValid { get { // Subject is required, Start must be before // End return !string.IsNullOrWhiteSpace(Subject) && DateTimeOffset.Compare(Start, End) < 0; } }添加以下代码,在页面加载时从 Microsoft Graph获取用户的时区。
protected override async void OnNavigatedTo(NavigationEventArgs e) { // Get the Graph client from the provider var graphClient = ProviderManager.Instance.GlobalProvider.Graph; try { // Get the user's mailbox settings to determine // their time zone var user = await graphClient.Me.Request() .Select(u => new { u.MailboxSettings }) .GetAsync(); _userTimeZone = TimeZoneInfo.FindSystemTimeZoneById(user.MailboxSettings.TimeZone); } catch (ServiceException graphException) { ShowNotification($"Exception getting user's mailbox settings from Graph, defaulting to local time zone: {graphException.Message}"); _userTimeZone = TimeZoneInfo.Local; } catch (Exception ex) { ShowNotification($"Exception loading time zone from system: {ex.Message}"); } } private void ShowNotification(string message) { // Get the main page that contains the InAppNotification var mainPage = (Window.Current.Content as Frame).Content as MainPage; // Get the notification control var notification = mainPage.FindName("Notification") as InAppNotification; notification.Show(message); }添加以下代码以创建事件。
private async void CreateEvent(object sender, RoutedEventArgs e) { CreateProgress.IsActive = true; CreateProgress.Visibility = Visibility.Visible; // Get the Graph client from the provider var graphClient = ProviderManager.Instance.GlobalProvider.Graph; // Initialize a new Event object with the required fields var newEvent = new Event { Subject = Subject, Start = Start.ToDateTimeTimeZone(_userTimeZone), End = End.ToDateTimeTimeZone(_userTimeZone) }; // If there's a body, add it if (!string.IsNullOrEmpty(Body)) { newEvent.Body = new ItemBody { Content = Body, ContentType = BodyType.Text }; } // Add any attendees var peopleList = AttendeePicker.Items.ToList(); var attendeeList = new List<Attendee>(); foreach (object entry in peopleList) { // People Picker can contain Microsoft.Graph.Person objects // or text entries (for email addresses not found in the user's people list) if (entry is Person) { var person = entry as Person; attendeeList.Add(new Attendee { Type = AttendeeType.Required, EmailAddress = new EmailAddress { Address = person.EmailAddresses.First().Address } }); } else if (entry is ITokenStringContainer) { var container = entry as ITokenStringContainer; // Treat any unrecognized text as a list of email addresses var emails = container.Text .Split(new[] { ';', ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (var email in emails) { try { // Validate the email address var addr = new System.Net.Mail.MailAddress(email); if (addr.Address == email) { attendeeList.Add(new Attendee { Type = AttendeeType.Required, EmailAddress = new EmailAddress { Address = email } }); } } catch { /* Invalid, skip */ } } } } if (attendeeList.Count > 0) { newEvent.Attendees = attendeeList; } try { await graphClient.Me.Events.Request().AddAsync(newEvent); } catch (ServiceException graphException) { ShowNotification($"Exception creating new event: ${graphException.Message}"); } CreateProgress.IsActive = false; CreateProgress.Visibility = Visibility.Collapsed; ShowNotification("Event created"); }修改
NavView_ItemInvokedMainPage.xaml.cs 文件中的方法,以将现有switch语句替换为以下内容。switch (invokedItem.ToLower()) { case "new event": RootFrame.Navigate(typeof(NewEventPage)); break; case "calendar": RootFrame.Navigate(typeof(CalendarPage)); break; case "home": default: RootFrame.Navigate(typeof(HomePage)); break; }保存更改并运行该应用程序。 登录,选择"新建事件"菜单项,填写表单,然后选择"创建"将事件添加到用户日历。

恭喜!
你已完成 UWP Microsoft Graph教程。 现在,你已经拥有一个调用 Microsoft Graph,你可以试验和添加新功能。 请访问Microsoft Graph概述,查看可以使用 Microsoft Graph 访问的所有数据。
反馈
Please provide any feedback on this tutorial in the GitHub repository.
你有关于此部分的问题? 如果有,请向我们提供反馈,以便我们对此部分作出改进。