|
Dieser Artikel wurde maschinell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen.
|
Übersetzung
Original
|
Vorgehensweise: Konfigurieren und Verwenden von Pushbenachrichtigungen in SharePoint 2013 apps für Windows Phone
|
|
Video ansehen: Verständnis und die Pushbenachrichtigungen in SharePoint 2013 entwickeln
|
So erstellen Sie das serverseitige-Projekt
-
Starten Sie Visual Studio 2012 mithilfe der Option als Administrator ausführen . -
Wählen Sie Datei, NeuesProjekt. Das Dialogfeld Neues Projekt angezeigt wird. -
Klicken Sie im Dialogfeld Neues Projekt den Knoten SharePoint unter Visual c#, und wählen Sie dann den Knoten 15 . -
Im Bereich Vorlagen wählen die Option SharePoint 15-Projekt , und geben Sie einen Namen für das Projekt, z.B.PushNotificationsList. -
Wählen Sie die Schaltfläche OK .Im SharePoint-Anpassungs-Assistent wird angezeigt.Dieses Assistenten können Sie die Zielwebsite für das entwickeln und Debuggen des Projekts und die Vertrauensebene der Lösung auswählen. -
Geben Sie die URL einer Website SharePoint Server .Wählen Sie eine Website, die Sie weiter unten in die Entwicklung von SharePoint-Liste-app für Windows Phone verwenden können. -
Wählen Sie als farmlösung bereitstellenaus, und klicken Sie dann auf Fertig stellen , um das Projekt zu erstellen.
So erstellen Sie die Klassen für die Verwaltung von Pushbenachrichtigungen
-
Wählen Sie im Projektmappen-Explorerden Knoten, das Projekt (namens PushNotificationsList Wenn Sie die in dieser Verfahren verwendeten Namenskonvention folgen) darstellt. -
Wählen Sie im Menü ProjektKlasse hinzufügen.Das Dialogfeld Neues Element hinzufügen wird angezeigt, mit der C#- Klasse -Vorlage bereits ausgewählt. -
Geben Sie PushNotification.cs als Namen der Datei, und klicken Sie auf Hinzufügen.Die Klassendatei ist die Lösung hinzugefügt und zur Bearbeitung geöffnet. -
Ersetzen Sie den Inhalt der Datei mit dem folgenden Code. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using Microsoft.SharePoint; namespace PushNotificationsList { internal static class WP7Constants { internal static readonly string[] WP_RESPONSE_HEADERS = { "X-MessageID", "X-DeviceConnectionStatus", "X-SubscriptionStatus", "X-NotificationStatus" }; } public enum TileIntervalValuesEnum { ImmediateTile = 1, Delay450SecondsTile = 11, Delay900SecondsTile = 21, } public enum ToastIntervalValuesEnum { ImmediateToast = 2, Delay450SecondsToast = 12, Delay900SecondsToast = 22, } public enum RawIntervalValuesEnum { ImmediateRaw = 3, Delay450SecondsRaw = 13, Delay900SecondsRaw = 23 } public enum NotificationTypeEnum { Tile = 1, Toast = 2, Raw = 3 } class PushNotification { public PushNotificationResponse PushToast(SPPushNotificationSubscriber subscriber, string toastTitle, string toastMessage, string toastParam, ToastIntervalValuesEnum intervalValue) { // Construct toast notification message from parameter values.string toastNotification = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<wp:Notification xmlns:wp=\"WPNotification\">" + "<wp:Toast>" + "<wp:Text1>" + toastTitle + "</wp:Text1>" + "<wp:Text2>" + toastMessage + "</wp:Text2>" + "<wp:Param>" + toastParam + "</wp:Param>" + "</wp:Toast> " + "</wp:Notification>"; return SendPushNotification(NotificationTypeEnum.Toast, subscriber, toastNotification, (int)intervalValue); } public PushNotificationResponse PushRaw(SPPushNotificationSubscriber subscriber, string rawMessage, RawIntervalValuesEnum intervalValue) { return SendPushNotification(NotificationTypeEnum.Raw, subscriber, rawMessage, (int)intervalValue); } private PushNotificationResponse SendPushNotification(NotificationTypeEnum notificationType, SPPushNotificationSubscriber subscriber, string message, int intervalValue) { // Create HTTP Web Request object.string subscriptionUri = subscriber.ServiceToken; HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri); // MPNS expects a byte array, so convert message accordingly.byte[] notificationMessage = Encoding.Default.GetBytes(message); // Set the notification request properties.sendNotificationRequest.Method = WebRequestMethods.Http.Post; sendNotificationRequest.ContentLength = notificationMessage.Length; sendNotificationRequest.ContentType = "text/xml"; sendNotificationRequest.Headers.Add("X-MessageID", Guid.NewGuid().ToString()); switch (notificationType) { case NotificationTypeEnum.Tile: sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "token"); break; case NotificationTypeEnum.Toast: sendNotificationRequest.Headers.Add("X-WindowsPhone-Target", "toast"); break; case NotificationTypeEnum.Raw: // A value for the X-WindowsPhone-Target header is not specified for raw notifications.break; } sendNotificationRequest.Headers.Add("X-NotificationClass", intervalValue.ToString()); // Merge byte array payload with headers.using (Stream requestStream = sendNotificationRequest.GetRequestStream()) { requestStream.Write(notificationMessage, 0, notificationMessage.Length); } string statCode = string.Empty; PushNotificationResponse notificationResponse; try { // Send the notification and get the response.HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse(); statCode = Enum.GetName(typeof(HttpStatusCode), response.StatusCode); // Create PushNotificationResponse object.notificationResponse = new PushNotificationResponse((int)intervalValue, subscriber.ServiceToken); notificationResponse.StatusCode = statCode; foreach (string header in WP7Constants.WP_RESPONSE_HEADERS) { notificationResponse.Properties[header] = response.Headers[header]; } } catch (Exception ex) { statCode = ex.Message; notificationResponse = new PushNotificationResponse((int)intervalValue, subscriber.ServiceToken); notificationResponse.StatusCode = statCode; } return notificationResponse; } } /// <summary> /// Object used for returning notification request results./// </summary> class PushNotificationResponse { private DateTime timestamp; private int notificationIntervalValue; private string statusCode = string.Empty; private string serviceToken; private Dictionary<string, string> properties; public PushNotificationResponse(int numericalIntervalValue, string srvcToken) { timestamp = DateTime.UtcNow; notificationIntervalValue = numericalIntervalValue; serviceToken = srvcToken; properties = new Dictionary<string, string>(); } public DateTime TimeStamp { get { return timestamp; } } public int NotificationIntervalValue { get { return notificationIntervalValue; } } public string StatusCode { get { return statusCode; } set { statusCode = value; } } public string ServiceToken { get { return serviceToken; } } public Dictionary<string, string> Properties { get { return properties; } } } }
-
Speichern Sie die Datei.
So erstellen Sie eine Liste die Ereignisempfängerklasse
-
Wählen Sie im Projektmappen-Explorerden Knoten, die das Projekt darstellen. -
Klicken Sie im Menü Projekt auf Klasse hinzufügen.Das Dialogfeld Neues Element hinzufügen wird angezeigt, mit der C#- Klasse -Vorlage bereits ausgewählt. -
Geben Sie ListItemEventReceiver.cs als Namen der Datei, und klicken Sie auf Hinzufügen.Die Klassendatei ist die Lösung hinzugefügt und zur Bearbeitung geöffnet. -
Ersetzen Sie den Inhalt der Datei mit dem folgenden Code. using System; using System.Security.Permissions; using System.Text; using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; namespace PushNotificationsList { /// <summary> /// List Item Events /// </summary> public class ListItemEventReceiver : SPItemEventReceiver { internal static string ResultsList = "Push Notification Results"; /// <summary> /// An item was added./// </summary> public override void ItemAdded(SPItemEventProperties properties) { SPWeb spWeb = properties.Web; SPPushNotificationSubscriberCollection pushSubscribers = spWeb.PushNotificationSubscribers; PushNotification pushNotification = new PushNotification(); SPListItem listItem = properties.ListItem; string jobAssignment = "[Unassigned]"; // This event receiver is intended to be associated with a specific list, // but the list may not have an "AssignedTo" field, so using try/catch here.try { jobAssignment = listItem["AssignedTo"].ToString(); } catch { } PushNotificationResponse pushResponse = null; foreach (SPPushNotificationSubscriber ps in pushSubscribers) { // Send a toast notification to be displayed on subscribed phones on which the app is not running.pushResponse = pushNotification.PushToast(ps, "New job for:", jobAssignment, string.Empty, ToastIntervalValuesEnum.ImmediateToast); UpdateNotificationResultsList(spWeb, ps.User.Name, pushResponse); // Also send a raw notification to be displayed on subscribed phones on which the app is running when the item is added.pushResponse = pushNotification.PushRaw(ps, string.Format("New job for: {0}", jobAssignment), RawIntervalValuesEnum.ImmediateRaw); UpdateNotificationResultsList(spWeb, ps.User.Name, pushResponse); } base.ItemAdded(properties); } private void UpdateNotificationResultsList(SPWeb spWeb, string subscriberName, PushNotificationResponse pushResponse) { SPList resultsList = spWeb.Lists.TryGetList(ResultsList); if (resultsList == null) return; try { SPListItem resultItem = resultsList.Items.Add(); resultItem["Title"] = subscriberName; resultItem["Notification Time"] = pushResponse.TimeStamp; resultItem["Status Code"] = pushResponse.StatusCode; resultItem["Service Token"] = pushResponse.ServiceToken; StringBuilder builder = new StringBuilder(); foreach (string key in pushResponse.Properties.Keys) { builder.AppendFormat("{0}: {1}; ", key, pushResponse.Properties[key]); } resultItem["Headers"] = builder.ToString(); resultItem["Interval Value"] = pushResponse.NotificationIntervalValue; resultItem.Update(); } catch { // Could log to ULS here if adding list item fails.} } } }
-
Speichern Sie die Datei.
Hinweis
|
|---|
|
|
To create a class for adding and configuring the lists
-
In Solution Explorer, choose the node representing the project (again, named PushNotificationsList if you follow the naming convention used in these procedures). -
On the Project menu, click Add Class.The Add New Item dialog box appears with the C# Class template already selected. -
Specify ListCreator.cs as the name of the file and click Add.The class file is added to the solution and opened for editing. -
Replace the contents of the file with the following code. using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using Microsoft.SharePoint; namespace PushNotificationsList { class ListCreator { internal void CreateJobsList(SPWeb spWeb) { string listTitle = "Jobs"; string listDescription = "List of jobs and assignments."; Dictionary<string, SPFieldType> columns = new Dictionary<string, SPFieldType>(); // The "Title" column will be added based on the GenericList template.That field // will be used as the category name for the job (e.g., Shopping), so only need to add // the remaining fields.columns.Add("Description", SPFieldType.Text); columns.Add("AssignedTo", SPFieldType.Text); // Creating list (or retrieving GUID for list if it already exists).Guid listId = CreateCustomList(spWeb, listTitle, listDescription, columns, false); if (listId.Equals(Guid.Empty)) return; SPList list = spWeb.Lists[listId]; // Add event receiver (if the current Jobs list is not already associated with the receiver).bool ReceiverExists = false; string receiverClassName = "PushNotificationsList.ListItemEventReceiver"; for (int i = 0; i < list.EventReceivers.Count; i++) { SPEventReceiverDefinition rd = list.EventReceivers[i]; if (rd.Class == receiverClassName && rd.Type == SPEventReceiverType.ItemAdded) { ReceiverExists = true; break; } } if (ReceiverExists == false) { SPEventReceiverDefinition eventReceiver = list.EventReceivers.Add(); // Must specify information here for this specific assembly.eventReceiver.Assembly = "PushNotificationsList, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=[YOUR TOKEN VALUE HERE]"; eventReceiver.Class = receiverClassName; eventReceiver.Name = "ItemAdded Event"; eventReceiver.Type = SPEventReceiverType.ItemAdded; eventReceiver.SequenceNumber = 10000; eventReceiver.Synchronization = SPEventReceiverSynchronization.Synchronous; eventReceiver.Update(); } } internal void CreateNotificationResultsList(SPWeb spWeb) { string listTitle = "Push Notification Results"; string listDescription = "List for results from push notification operations."; Dictionary<string, SPFieldType> columns = new Dictionary<string, SPFieldType>(); columns.Add("Notification Time", SPFieldType.Text); columns.Add("Status Code", SPFieldType.Text); columns.Add("Service Token", SPFieldType.Text); columns.Add("Headers", SPFieldType.Text); columns.Add("Interval Value", SPFieldType.Integer); // Creating the list for storing notification results.CreateCustomList(spWeb, listTitle, listDescription, columns, true); } /// <summary> /// Creates a SharePoint list (based on the Generic List template)./// </summary> /// <param name="spWeb">The target Web site for the list.</param> /// <param name="listTitle">The title of the list.</param> /// <param name="listDescription">A description for the list.</param> /// <param name="columns">A Dictionary object containing field names and types.</param> /// <param name="replaceExistingList">Indicates whether to overwrite an existing list of the same name on the site.</param> /// <returns>A GUID for the created (or existing) list.</returns> internal Guid CreateCustomList(SPWeb spWeb, string listTitle, string listDescription, Dictionary<string, SPFieldType> columns, bool replaceExistingList) { SPList list = spWeb.Lists.TryGetList(listTitle); if (list != null) { if (replaceExistingList == true) { try { list.Delete(); } catch { return Guid.Empty; } } else { return list.ID; } } try { Guid listId = spWeb.Lists.Add(listTitle, listDescription, SPListTemplateType.GenericList); list = spWeb.Lists[listId]; SPView view = list.DefaultView; foreach (string key in columns.Keys) { list.Fields.Add(key, columns[key], false); view.ViewFields.Add(key); } list.Update(); view.Update(); return listId; } catch { return Guid.Empty; } } } }
Be sure to specify the appropriate Public Key Token value for particular your assembly.To add a tool to Visual Studio for getting the Public Key Token value for your assembly, see How to: Create a Tool to Get the Public Key of an Assembly in the MSDN Library.Note that you will have to compile your project at least once to be able to get the Public Key Token value for your output assembly. -
Speichern Sie die Datei.
To add a Feature to your project
-
In Visual Studio 2012, on the View menu, point to Other Windows and then click Packaging Explorer. -
In the Packaging Explorer, right-click the node representing your project and click Add Feature.A new Feature (named "Feature1" by default) is added to your project, under a Features node (in Solution Explorer). -
Now, in Solution Explorer, under the Features node, right-click the newly added Feature (that is, Feature1), and click Add Event Receiver.An event receiver class file (Feature1.EventReceiver.cs) is added to the Feature and opened for editing. -
Within the implementation (demarcated by opening and closing braces) of the Feature1EventReceiver class, add the following code. internal const string PushNotificationFeatureId = "41E1D4BF-B1A2-47F7-AB80-D5D6CBBA3092";
This string variable stores the identifier for the Push Notification Feature on the server.
Tipp
You can obtain a list of unique identifiers for the Features on a SharePoint Server by executing the following Windows PowerShell cmdlet: Get-SPFeature | Sort -Property DisplayName The Push Notification Feature appears as "PhonePNSubscriber" in the results returned by this cmdlet. -
The event receiver class file is created with some default method declarations for handling Feature events.The method declarations in the file are initially commented out.Replace the FeatureActivated method in the file with the following code. public override void FeatureActivated(SPFeatureReceiverProperties properties) { base.FeatureActivated(properties); SPWeb spWeb = (SPWeb)properties.Feature.Parent; ListCreator listCreator = new ListCreator(); listCreator.CreateJobsList(spWeb); listCreator.CreateNotificationResultsList(spWeb); // Then activate the Push Notification Feature on the server.// The Push Notification Feature is not activated by default in a SharePoint Server installation.spWeb.Features.Add(new Guid(PushNotificationFeatureId), false); }
-
Replace the FeatureDeactivating method in the file with the following code. public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { base.FeatureDeactivating(properties); SPWeb spWeb = (SPWeb)properties.Feature.Parent; // Deactivate the Push Notification Feature on the server // when the PushNotificationsList Feature is deactivated.spWeb.Features.Remove(new Guid(PushNotificationFeatureId), false); }
-
Speichern Sie die Datei.
To create the class for managing subscriptions and received notifications
-
In Solution Explorer, choose the node representing the project (named SPListAppForNotifications). -
On the Project menu, click Add Class.The Add New Item dialog box appears with the C# Class template already selected. -
Specify "Notifications.cs" as the name of the file and click Add.The class file is added to the solution and opened for editing. -
Replace the contents of the file with the following code. using System; using System.Linq; using System.Net; using System.Windows; using Microsoft.Phone.Notification; using Microsoft.SharePoint.Client; using System.Diagnostics; using System.Collections.Generic; using Microsoft.Phone.Shell; using System.IO; using System.IO.IsolatedStorage; namespace SPListAppForNotifications { public class Notifications { static HttpNotificationChannel httpChannel; private const string RegStatusKey = "RegistrationStatus"; public static string DeviceAppIdKey = "DeviceAppInstanceId"; public static string ChannelName = "JobsListNotificationChannel"; public static ClientContext Context { get; set; } public static void OpenNotificationChannel(bool isInitialRegistration) { try { // Get channel if it was created in a previous session of the app.httpChannel = HttpNotificationChannel.Find(ChannelName); // If channel is not found, create one.if (httpChannel == null) { httpChannel = new HttpNotificationChannel(ChannelName); // Add event handlers.When the Open method is called, the ChannelUriUpdated event will fire.// A call is made to the SubscribeToService method in the ChannelUriUpdated event handler.AddChannelEventHandlers(); httpChannel.Open(); } else { // The channel exists and is already open.Add handlers for channel events.// The ChannelUriUpdated event won't fire in this case.AddChannelEventHandlers(); // If app instance is registering for first time // (instead of just starting up again), then call SubscribeToService.if (isInitialRegistration) { SubscribeToService(); } } } catch (Exception ex) { ShowMessage(ex.Message, "Error Opening Channel"); CloseChannel(); } } private static void AddChannelEventHandlers() { httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated); httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ExceptionOccurred); httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived); httpChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(httpChannel_HttpNotificationReceived); } private static void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e) { UpdateChannelUriOnServer(); SubscribeToService(); } private static void httpChannel_ExceptionOccurred(object sender, NotificationChannelErrorEventArgs e) { // Simply showing the exception error.ShowMessage(e.Message, "Channel Event Error"); } static void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e) { if (e.Collection != null) { Dictionary<string, string> collection = (Dictionary<string, string>)e.Collection; ShellToast toast = new ShellToast(); toast.Title = collection["wp:Text1"]; toast.Content = collection["wp:Text2"]; // Note that the Show method for a toast notification won't // display the notification in the UI of the phone when the app // that calls the method is running (as the foreground app on the phone).// toast.Show(); //Toast and Raw notification will be displayed if user is running the app.Be default only Toast notification // will be displayed when the app is tombstoned // Showing the toast notification with the ShowMessage method.ShowMessage(string.Format("Title: {0}\r\nContent: {1}", toast.Title, toast.Content), "Toast Notification"); } } static void httpChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e) { Stream messageStream = e.Notification.Body; string message = string.Empty; // Replacing NULL characters in stream.using (var reader = new StreamReader(messageStream)) { message = reader.ReadToEnd().Replace('\0', ' '); } // Simply displaying the raw notification.ShowMessage(message, "Raw Notification"); } private static void SubscribeToService() { Guid deviceAppInstanceId = GetSettingValue<Guid>(DeviceAppIdKey, false); Context.Load(Context.Web, w => w.Title, w => w.Description); PushNotificationSubscriber pushSubscriber = Context.Web.RegisterPushNotificationSubscriber(deviceAppInstanceId, httpChannel.ChannelUri.AbsoluteUri); Context.Load(pushSubscriber); Context.ExecuteQueryAsync ( (object sender, ClientRequestSucceededEventArgs args) => { SetRegistrationStatus(true); // Indicate that tile and toast notifications can be // received by phone shell when phone app is not running.if (!httpChannel.IsShellTileBound) httpChannel.BindToShellTile(); if (!httpChannel.IsShellToastBound) httpChannel.BindToShellToast(); ShowMessage( string.Format("Subscriber successfully registered: {0}", pushSubscriber.User.LoginName), "Success"); }, (object sender, ClientRequestFailedEventArgs args) => { ShowMessage(args.Exception.Message, "Error Subscribing"); }); } private static void UpdateChannelUriOnServer() { Guid deviceAppInstanceId = GetSettingValue<Guid>(DeviceAppIdKey, false); Context.Load(Context.Web, w => w.Title, w => w.Description); PushNotificationSubscriber subscriber = Context.Web.GetPushNotificationSubscriber(deviceAppInstanceId); Context.Load(subscriber); Context.ExecuteQueryAsync( (object sender1, ClientRequestSucceededEventArgs args1) => { subscriber.ServiceToken = httpChannel.ChannelUri.AbsolutePath; subscriber.Update(); Context.ExecuteQueryAsync( (object sender2, ClientRequestSucceededEventArgs args2) => { ShowMessage("Channel URI updated on server.", "Success"); }, (object sender2, ClientRequestFailedEventArgs args2) => { ShowMessage(args2.Exception.Message, "Error Upating Channel URI"); }); }, (object sender1, ClientRequestFailedEventArgs args1) => { // This condition can be ignored.Getting to this point means the subscriber // doesn't yet exist on the server, so updating the Channel URI is unnecessary.//ShowMessage("Subscriber doesn't exist on server.", "DEBUG"); }); } public static void UnSubscribe() { Context.Load(Context.Web, w => w.Title, w => w.Description); Guid deviceAppInstanceId = GetSettingValue<Guid>(DeviceAppIdKey, false); Context.Web.UnregisterPushNotificationSubscriber(deviceAppInstanceId); Context.ExecuteQueryAsync ( (object sender, ClientRequestSucceededEventArgs args) => { CloseChannel(); SetRegistrationStatus(false); //SetInitializationStatus(false); ShowMessage("Subscriber successfully unregistered.", "Success"); }, (object sender, ClientRequestFailedEventArgs args) => { ShowMessage(args.Exception.Message, "Error Unsubscribing"); }); } public static void ClearSubscriptionStore() { Context.Load(Context.Web, w => w.Title, w => w.Description); List subscriptionStore = Context.Web.Lists.GetByTitle("Push Notification Subscription Store"); Context.Load(subscriptionStore); ListItemCollection listItems = subscriptionStore.GetItems(new CamlQuery()); Context.Load(listItems); Context.ExecuteQueryAsync ( (object sender1, ClientRequestSucceededEventArgs args1) => { foreach (ListItem listItem in listItems.ToList()) { listItem.DeleteObject(); } Context.ExecuteQueryAsync( (object sender2, ClientRequestSucceededEventArgs args2) => { // Close channel if open and set registration status for current app instance.CloseChannel(); SetRegistrationStatus(false); ShowMessage("Subscriber store cleared.", "Success"); }, (object sender2, ClientRequestFailedEventArgs args2) => { ShowMessage(args2.Exception.Message, "Error Deleting Subscribers"); }); }, (object sender1, ClientRequestFailedEventArgs args1) => { ShowMessage(args1.Exception.Message, "Error Loading Subscribers List"); }); } private static void CloseChannel() { if (httpChannel == null) return; try { httpChannel.UnbindToShellTile(); httpChannel.UnbindToShellToast(); httpChannel.Close(); } catch (Exception ex) { ShowMessage(ex.Message, "Error Closing Channel"); } } public static void SaveDeviceAppIdToStorage() { if (!IsolatedStorageSettings.ApplicationSettings.Contains(DeviceAppIdKey)) { Guid DeviceAppId = Guid.NewGuid(); SetSettingValue<Guid>(DeviceAppIdKey, DeviceAppId, false); } } public static bool GetRegistrationStatus() { bool status = GetSettingValue<bool>(RegStatusKey, false); return status; } private static void SetRegistrationStatus(bool isRegistered) { SetSettingValue<bool>(RegStatusKey, isRegistered, false); } private static T GetSettingValue<T>(string key, bool fromTransientStorage) { if (fromTransientStorage == false) { if (IsolatedStorageSettings.ApplicationSettings.Contains(key)) return (T)IsolatedStorageSettings.ApplicationSettings[key]; return default(T); } if (PhoneApplicationService.Current.State.ContainsKey(key)) return (T)PhoneApplicationService.Current.State[key]; return default(T); } private static void SetSettingValue<T>(string key, T value, bool toTransientStorage) { if (toTransientStorage == false) { if (IsolatedStorageSettings.ApplicationSettings.Contains(key)) IsolatedStorageSettings.ApplicationSettings[key] = value; else IsolatedStorageSettings.ApplicationSettings.Add(key, value); IsolatedStorageSettings.ApplicationSettings.Save(); } else { if (PhoneApplicationService.Current.State.ContainsKey(key)) PhoneApplicationService.Current.State[key] = value; else PhoneApplicationService.Current.State.Add(key, value); } } // Method for showing messages on UI thread coming from a different originating thread.private static void ShowMessage(string message, string caption) { Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show(message, caption, MessageBoxButton.OK); }); } } }
-
Speichern Sie die Datei.
To add a notification settings page to the app
-
In Solution Explorer, choose the node representing the project (named SPListAppForNotifications if you follow the naming convention in these procedures). -
On the Project menu, click Add New Item.The Add New Item dialog box appears. -
In the Templates pane, choose Windows Phone Portrait Page template.Specify Settings.xaml as the name of the file for the page and click Add.The page is added to the project and opened for editing. -
In the XAML view for the page, replace the content between the closing bracket of the XML tag that defines the PhoneApplicationPage element and the closing tag of the element (</phone:PhoneApplicationPage>), with the following markup. <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel contains the name of the application and page title--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="JOBS LIST" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="Settings" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <StackPanel Margin="0,5,0,5"> <StackPanel Orientation="Vertical" Margin="0,5,0,5"> <TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Style="{StaticResource PhoneTextTitle2Style}">Notification Registration</TextBlock> <StackPanel Orientation="Vertical" Margin="0,5,0,5"> <TextBlock x:Name="txtRegistrationStatus" TextWrapping="Wrap" HorizontalAlignment="Center" Text="Registered: No" Style="{StaticResource PhoneTextAccentStyle}" Foreground="{StaticResource PhoneAccentBrush}" /> <Button x:Name="btnRegister" Content="Register" Height="71" Width="260" Click="OnRegisterButtonClick" /> <Button x:Name="btnUnregister" Content="Unregister" Height="71" Width="260" Click="OnUnregisterButtonClick" /> </StackPanel> </StackPanel> <StackPanel Orientation="Vertical" Margin="0,5,0,5"> <TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" Style="{StaticResource PhoneTextTitle2Style}">Subscriber Management</TextBlock> <Button x:Name="btnDeleteSubscribers" Content="Delete Subscribers" Height="71" Width="260" Click="OnDeleteSubscribersButtonClick" /> </StackPanel> </StackPanel> </Grid> </Grid> <!--Sample code showing usage of ApplicationBar--> <phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="False"> <shell:ApplicationBarIconButton x:Name="btnOK" IconUri="/Images/appbar.check.rest.png" Text="OK" Click="OnOKButtonClick" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
-
With the Settings.xaml file selected in Solution Explorer, press F7 to open its associated code-behind file, Settings.xaml.cs, for editing. -
Replace the contents of the code-behind file with the following code. using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using Microsoft.Phone.Controls; using Microsoft.SharePoint.Client; namespace SPListAppForNotifications { public partial class Settings : PhoneApplicationPage { private const string RegisteredYesText = "Registered: Yes"; private const string RegisteredNoText = "Registered: No"; public Settings() { InitializeComponent(); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { this.txtRegistrationStatus.Text = (Notifications.GetRegistrationStatus()) ?RegisteredYesText : RegisteredNoText; } private void OnOKButtonClick(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative)); } private void OnRegisterButtonClick(object sender, RoutedEventArgs e) { Notifications.OpenNotificationChannel(true); // Navigating back to List form.User will be notified when process is complete.NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative)); } private void OnUnregisterButtonClick(object sender, RoutedEventArgs e) { Notifications.UnSubscribe(); // Navigating back to List form.User will be notified when process is complete.NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative)); } private void OnDeleteSubscribersButtonClick(object sender, RoutedEventArgs e) { Notifications.ClearSubscriptionStore(); // Navigating back to List form.User will be notified when process is complete.NavigationService.Navigate(new Uri("/Views/List.xaml", UriKind.Relative)); } } }
-
Speichern Sie die Datei. -
To add to your project the image file (appbar.check.rest.png) for the ApplicationBar button (btnOK) declared in the Settings.xaml file, choose the Images folder node in Solution Explorer. -
On the Project menu, click Add Existing Item.A File Browser window opens. -
Navigate to the folder in which the standard Windows Phone icon images were installed by the Windows Phone SDK 7.1.
Hinweis
Die Bilder mit einem oberflächliche Vorder- und Hintergrund dunkel sind in % Programme %(x86) \Microsoft SDKs\Windows Phone\v7.1\Icons\dark in einer Standardinstallation von SDK. -
Wählen Sie die Bilddatei, die mit dem Namen appbar.check.rest.png, und klicken Sie auf Hinzufügen.Das Bild wird hinzugefügt wird dem Projekt unter den Knoten Bilder hinzugefügt. -
Wählen Sie im Projektmappen-Explorerdie Bilddatei nur hinzugefügt und legen Sie die Eigenschaft Buildvorgang für die Bilddatei auf "Content" in das Fenster Eigenschaften für die Datei, und legen Sie die Kopie in Ausgabeverzeichnis -Eigenschaft auf "Kopie wenn neuer".
Zum Ändern des Listenformulars
-
Doppelklicken Sie im Projektmappen-Explorerunter dem Knoten Ansichten auf die Datei List.xaml.Die Datei wird zur Bearbeitung geöffnet. -
Fügen Sie-Markups zum Deklarieren Sie einer zusätzlichen Schaltfläche im ApplicationBar -Element der Datei, wie im folgenden Beispiel. ...<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> <shell:ApplicationBarIconButton x:Name="btnNew" IconUri="/Images/appbar.new.rest.png" Text="New" Click="OnNewButtonClick" /> <shell:ApplicationBarIconButton x:Name="btnRefresh" IconUri="/Images/appbar.refresh.rest.png" Text="Refresh" IsEnabled="True" Click="OnRefreshButtonClick" /> <shell:ApplicationBarIconButton x:Name="btnSettings" IconUri="/Images/appbar.feature.settings.rest.png" Text="Settings" IsEnabled="True" Click="OnSettingsButtonClick" /> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar> ...
-
Drücken der List.xaml-Datei im Projektmappen-ExplorerausgewähltF7zugehörige Code-Behind-Datei, List.xaml.cs, zur Bearbeitung zu öffnen. -
Innerhalb der Codeblock (abgegrenzt durch Öffnen und schließen die geschweiften Klammern), der die partiellen ListForm -Klasse implementiert wird, fügen Sie den folgenden Ereignishandler an der Datei. private void OnSettingsButtonClick(object sender, EventArgs e) { NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative)); }
-
Suchen Sie die OnViewModelInitialization in der List.xaml.cs-Datei, und fügen Sie einen Anruf an die OpenNotificationChannel -Methode der zuvor erstellten Notifications -Klasse.Die geänderte Implementierung des Handlers sollte mit dem folgenden Code ähneln. private void OnViewModelInitialization(object sender, InitializationCompletedEventArgs e) { this.Dispatcher.BeginInvoke(() => { //If initialization has failed, show error message and return if (e.Error != null) { MessageBox.Show(e.Error.Message, e.Error.GetType().Name, MessageBoxButton.OK); return; } App.MainViewModel.LoadData(((PivotItem)Views.SelectedItem).Name); this.DataContext = (sender as ListViewModel); }); // Open notification channel here if user has chosen to subscribe to notifications.if (Notifications.GetRegistrationStatus() == true) Notifications.OpenNotificationChannel(false); }
-
Speichern Sie die Datei. -
Sie dem Projekt die Bilddatei (appbar.feature.settings.rest.png) für die Schaltfläche mit den ApplicationBar (BtnSettings) in der Datei List.xaml deklariert hinzuzufügen, wählen Sie den Knoten der Bilder Ordner im Projektmappen-Explorer. -
Klicken Sie im Menü Projekt auf Vorhandenes Element hinzufügen.Eine Datei-Browserfenster geöffnet wird. -
Navigieren Sie zu dem Ordner, in dem der standard Symbolbilder für Windows Phone vom Windows Phone SDK 7.1 installiert wurden.(Siehe den Hinweis im vorherigen Verfahren für den Speicherort der Bilddateien in einer Standardinstallation von SDK.) -
Wählen Sie die Bilddatei, die mit dem Namen appbar.feature.settings.rest.png, und klicken Sie auf Hinzufügen.Das Bild wird hinzugefügt wird dem Projekt unter den Knoten Bilder hinzugefügt. -
Wählen Sie im Projektmappen-Explorerdie Bilddatei nur hinzugefügt und legen Sie die Eigenschaft Buildvorgang für die Bilddatei auf "Content" in das Fenster Eigenschaften für die Datei, und legen Sie die Kopie in Ausgabeverzeichnis -Eigenschaft auf "Kopie wenn neuer".
Die Datei App.xaml.cs Code hinzu
-
Wählen Sie im Projektmappen-Explorerunter dem Knoten, die das Projekt darstellen aus die Datei App.xaml. -
TastenkombinationF7zugeordnete Code-Behind-Datei, App.xaml.cs, zur Bearbeitung zu öffnen. -
Suchen Sie den Application_Launching -Ereignishandler in der Datei.(Für neue Projekte aus der Liste-Anwendung für Windows Phone SharePoint-Vorlage erstellt, die Signatur für die Methode, die für die Application_Launching Ereignisbehandlung eingeschlossen ist jedoch keine Logik wird in der-Methode implementiert.) -
Ersetzen Sie den Application_Launching -Ereignishandler mit dem folgenden Code. private void Application_Launching(object sender, LaunchingEventArgs e) { // Get set up for notifications.Notifications.Context = App.DataProvider.Context; Notifications.SaveDeviceAppIdToStorage(); }
-
Speichern Sie die Datei.