/// <summary> /// Invokes the specified method on the feature object in Mowbly javascript layer, with the result as argument. /// </summary> /// <param name="obj">The object to invoke the method on in Mowbly javascript layer</param> /// <param name="method">The method to call in Mowbly javascript layer</param> /// <param name="r">The /// <see cref="CloudPact.MowblyFramework.Core.Features.MethodResult">MethodResult</see> /// object to send to Mowbly javascript layer.</param> internal void InvokeJavascript(string obj, string method, MethodResult r) { UiDispatcher.BeginInvoke(() => { Page.InvokeJavascript(obj, method, new Object[] { r }); }); }
/// <summary> /// Invoke the method specified by the /// <see cref="CloudPact.MowblyFramework.Core.Features.JSMessage">JSMessage</see> object /// </summary> /// <param name="message"> /// <see cref="CloudPact.MowblyFramework.Core.Features.JSMessage">JSMessage</see> object /// </param> internal async override void InvokeAsync(JSMessage message) { try { switch (message.Method) { case "sendMail": List <string> toList = ((JToken)message.Args[0]).ToObject <List <string> >(); string subject = message.Args[1] as string; string body = message.Args[2] as string; List <string> ccList = ((JToken)message.Args[3]).ToObject <List <string> >(); List <string> bccList = ((JToken)message.Args[4]).ToObject <List <string> >(); // Create email compose task and display EmailComposeTask emailComposeTask = new EmailComposeTask(); emailComposeTask.To = String.Join("; ", toList); emailComposeTask.Subject = subject; emailComposeTask.Body = body; emailComposeTask.Cc = String.Join("; ", ccList); emailComposeTask.Bcc = String.Join("; ", bccList); UiDispatcher.BeginInvoke(() => { emailComposeTask.Show(); }); // Set app navigated to external page Mowbly.AppNavigatedToExternalPage = true; break; case "sendText": case "sendData": // Create sms compose task and show List <string> phoneNumbers = ((JToken)message.Args[0]).ToObject <List <string> >(); string text = message.Args[1] as string; SmsComposeTask smsComposeTask = new SmsComposeTask(); smsComposeTask.To = String.Join(";", phoneNumbers); smsComposeTask.Body = text; UiDispatcher.BeginInvoke(() => { smsComposeTask.Show(); }); // Set app navigated to external page Mowbly.AppNavigatedToExternalPage = true; break; default: Logger.Error("Feature " + Name + " does not support method " + message.Method); break; } } catch (Exception ce) { Logger.Error("Exception occured. Reason - " + ce.Message); } await Task.FromResult(0); }
private async Task DoInstallAndRaiseAsync() { string password = null; if (HasPassword && !string.IsNullOrEmpty(Password) && !string.IsNullOrWhiteSpace(Password)) { password = Password; } try { bool isInstalled = await Database.DatabaseProvider.InstallAsync(password); if (isInstalled) { await UiDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(RaisePropertyChangedToViewModel)); } } catch (Exception exception) { MessageBoxHelper.ShowMessage(exception.Message, "Failed to install Database", MessageBoxButton.OK, MessageBoxImage.Error); } }
// background thread private void ChangePassword(object state) { OfxRequest req = new OfxRequest(this.account, this.money, null); try { req.ChangePassword(this.account, newPassword, out logFile); } catch (Exception e) { Error = e; } if (cancelled) { return; } UiDispatcher.BeginInvoke(new Action(() => { if (this.Error != null) { // The error might be about the new password being invalid for some reason, so show // the message and let user try again. ShowError(this.Error.Message); EnableButtons(); } else { this.DialogResult = true; this.account.Password = this.GetUserDefinedField("NewPassword"); this.Close(); } })); }
private void FiterEventTextChanged(string filter) { if (FilterValueChanged != null) { UiDispatcher.BeginInvoke(FilterValueChanged, this, filter); } }
/// <summary> /// Notifies the user interface registered controls based on the current state and the new position of the cursor position. /// </summary> /// <param name="normalizedX">New X position of the kinect cursor</param> /// <param name="normalizedY">New Y position of the kinect cursor</param> /// <param name="hasCursorPositionChanged">Boolean that indicates whether the normalizedX and normalizedY values are identical to the previous values</param> protected void UpdateControls(double normalizedX, double normalizedY, bool hasCursorPositionChanged) { UiDispatcher.BeginInvoke(new Action(() => { var newActiveControl = GetActiveControl(normalizedX, normalizedY); if (newActiveControl == currentActiveControl) { if (newActiveControl != null && hasCursorPositionChanged) { newActiveControl.TriggerCursorMove(new KinectUiEventArgs() { NormalizedX = normalizedX, NormalizedY = normalizedY }); } if (newActiveControl != null && newActiveControl.IsActivationEnabled) { var elapsed = DateTime.Now - this.ActiveControlEnterTime; var normalizedTime = Math.Min(1.0, elapsed.TotalMilliseconds / newActiveControl.ActivationTime.Value); if (!IsControlActivated) { this.UpdateCursorsActivationProgress(normalizedTime); } if (normalizedTime == 1.0 && !IsControlActivated) { newActiveControl.TriggerActivation(new KinectUiEventArgs() { NormalizedX = normalizedX, NormalizedY = normalizedY }); IsControlActivated = true; } } } else { if (newActiveControl != null) { newActiveControl.TriggerCursorEnter(new KinectUiEventArgs() { NormalizedX = normalizedX, NormalizedY = normalizedY }); this.ActiveControlEnterTime = DateTime.Now; } if (currentActiveControl != null) { currentActiveControl.TriggerCursorLeave(new KinectUiEventArgs() { NormalizedX = normalizedX, NormalizedY = normalizedY }); this.StopCursorsActivationCountdown(); } IsControlActivated = false; this.UpdateCursorsActivationProgress(0.0); } currentActiveControl = newActiveControl; })); }
void BeginGetQuotes(HashSet <Security> toFetch) { if (_services.Count == 0 || toFetch.Count == 0) { return; } UiDispatcher.BeginInvoke(new Action(() => { OutputPane output = (OutputPane)provider.GetService(typeof(OutputPane)); output.Clear(); output.AppendHeading(Walkabout.Properties.Resources.StockQuoteCaption); })); List <string> batch = new List <string>(); foreach (Security s in toFetch) { if (string.IsNullOrEmpty(s.Symbol)) { continue; // skip it. } batch.Add(s.Symbol); } bool foundService = false; IStockQuoteService service = GetHistoryService(); HistoryDownloader downloader = GetDownloader(service); if (service != null) { downloader.BeginFetchHistory(batch); foundService = true; } service = GetQuoteService(); if (service != null) { foundService = true; if (service.SupportsBatchQuotes) { service.BeginFetchQuotes(batch); } else { foreach (var item in batch) { service.BeginFetchQuote(item); } } } if (!foundService) { AddError(Walkabout.Properties.Resources.ConfigureStockQuoteService); UiDispatcher.BeginInvoke(new Action(UpdateUI)); } }
/// <summary> /// Invokes the CallbackClient receive method in Mowbly javascript layer /// </summary> /// <param name="method">The method to call in Mowbly javascript layer</param> /// <param name="r">The /// <see cref="CloudPact.MowblyFramework.Core.Features.MethodResult">MethodResult</see> /// object to send to Mowbly javascript layer.</param> internal void InvokeCallbackJavascript(string callbackId, MethodResult r) { if (!string.IsNullOrEmpty(callbackId)) { UiDispatcher.BeginInvoke(() => { Page.InvokeJavascript("__mowbly__.__CallbackClient", "onreceive", new Object[] { callbackId, r }); }); } }
/// <summary> /// Invokes the CallbackClient receive method in Mowbly javascript layer /// </summary> /// <param name="method">The method to call in Mowbly javascript layer</param> /// <param name="arg">Argument to be sent to the callback method mowbly javascript layer</param> internal void InvokeCallbackJavascript(string callbackId, object arg) { if (!string.IsNullOrEmpty(callbackId)) { UiDispatcher.BeginInvoke(() => { Page.InvokeJavascript("__mowbly__.__CallbackClient", "onreceive", callbackId, arg); }); } }
public void OnLogMessageRecieved(object sender, MessageRecievedEventArgs e) { UiDispatcher.BeginInvoke(new Action(() => { LogList.Insert(0, new Tuple <SolidColorBrush, EventLogEntryType, string>( GetMessageTypeColor(e.EventLogEntryType), e.EventLogEntryType, e.Message)); NotifyPropertyChanged("LogList"); })); }
public void RunOnUIThread(Action action, DispatcherPriority priority = DispatcherPriority.Normal) { if (UiDispatcher == null) { action(); } else { UiDispatcher.BeginInvoke(action, priority); } }
internal void Reset() { UiDispatcher.BeginInvoke(() => { // Close all pages CloseAllPages(); // Clear active page activePage = null; }); }
private void LoadGameDirectoriesAsync() { Task.Run(async() => { IList <FromSoftwareFile> loadGameRootDirectories = await FileRepository.LoadGameDirectoriesAsync(); foreach (FromSoftwareFile fromSoftwareFile in loadGameRootDirectories) { await UiDispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { _gameRootsDirectory.Add(new RootDirectoryViewModel(this, fromSoftwareFile)); })); } }); }
void LaunchPage(string pageName, string url) { Dictionary <string, object> options = new Dictionary <string, object> { { "retainPageInViewStack", true }, { "showProgress", true } }; UiDispatcher.BeginInvoke(() => { PageManager.Instance.OpenPage(pageName, url, null, options); }); }
/// <summary> /// This runs on a background thread and finds all attachments and updates the HasAttachment /// flag on all transactions. /// </summary> /// <param name="state"></param> public void ScanDirectory() { // set of transactions that have attachments. Thread.Sleep(1000); // give app time to startup... #if PerformanceBlocks using (PerformanceBlock.Create(ComponentId.Money, CategoryId.Model, MeasurementId.ScanAttachments)) { #endif try { string path = this.AttachmentDirectory; if (!string.IsNullOrEmpty(path) && Directory.Exists(path) && this.money != null) { // process pending account checks Account a; while (accountQueue.TryDequeue(out a) && threadRunning) { FindAttachments(path, a); } // process pending individual transaction checks. List <Tuple <Transaction, bool> > toUpdate = new List <Tuple <Transaction, bool> >(); Transaction t; while (transactionQueue.TryDequeue(out t) && threadRunning) { bool yes = HasAttachments(path, t); if (t.HasAttachment != yes) { toUpdate.Add(new Tuple <Transaction, bool>(t, yes)); } } // Updating Money transactions has to happen on the UI thread. UiDispatcher.BeginInvoke(new Action(() => { BatchUpdate(toUpdate); })); } } catch { } #if PerformanceBlocks } #endif threadRunning = false; threadStopEvent.Set(); }
/// <summary> /// Posts a javascript message to the specified page /// </summary> /// <param name="pageName">Name of the page to which message will be sent</param> /// <param name="message">Message to send</param> internal async Task PostMessageToPageAsync(string pageName, string message) { PageModel page = pages.Where(p => p.Name == pageName).FirstOrDefault(); if (page != null) { await Task.Run(() => { UiDispatcher.BeginInvoke(() => { page.InvokeJavascript("__mowbly__", "_onPageMessage", new object[] { message, activePage.Name }); }); }); } }
/// <summary> /// Notifies the cursors that the activation process has been stopped. /// </summary> private void StopCursorsActivationCountdown() { UiDispatcher.BeginInvoke(new Action(() => { IKinectCursor[] cursorArray; lock (cursorDictionarySync) { cursorArray = cursorDictionary.Values.ToArray(); } foreach (var cursor in cursorArray) { cursor.StopActivationCountdown(); } })); }
/// <summary> /// When a KinectUiControl is activating, updates the cursors with the updated countdown according to the activeControl activation time. /// </summary> /// <param name="normalizedTime">Value from 0 to 1 that represents the progress of the activation process.</param> private void UpdateCursorsActivationProgress(double normalizedTime) { UiDispatcher.BeginInvoke(new Action(() => { IKinectCursor[] cursorArray; lock (cursorDictionarySync) { cursorArray = cursorDictionary.Values.ToArray(); } foreach (var cursor in cursorArray) { cursor.SetActivationCountdownProgress(normalizedTime); } })); }
/// <summary> /// Invokes the specified javascript message on all pages /// </summary> /// <param name="message">Javascript message</param> internal async Task BroadcastMessageAsync(string message) { foreach (PageModel page in pages) { if (page != activePage) { await Task.Run(() => { UiDispatcher.BeginInvoke(() => { page.InvokeJavascript("__mowbly__", "_onPageMessage", new object[] { message, activePage.Name }); }); }); } } }
private void OnInstallationFinished(Task task) { _dispatcher.BeginInvoke(() => { if (task.IsFaulted) { InstallationResult = "failed"; HasFailed = true; ErrorMessage = FormatErrorMessage(task.Exception); IsPostInstallation = true; } else { _installer.Launch(); Application.Current.Shutdown(); } }); }
private void OnServiceQuotesComplete(object sender, DownloadCompleteEventArgs args) { if (!string.IsNullOrEmpty(args.Message)) { AddError(args.Message); } if (args.Complete) { Tuple <int, int> progress = GetProgress(); status.ShowProgress("", 0, progress.Item1, progress.Item2); if (!disposed) { OnDownloadComplete(); } } UiDispatcher.BeginInvoke(new Action(UpdateUI)); }
/// <summary> /// Updates the cursors with the updated position. /// </summary> /// <param name="normalizedX">New X position of the kinect cursor</param> /// <param name="normalizedY">New Y position of the kinect cursor</param> /// <param name="hasCursorPositionChanged">Boolean that indicates whether the normalizedX and normalizedY values are identical to the previous values</param> protected void UpdateCursors(double normalizedX, double normalizedY, bool hasCursorPositionChanged) { if (!hasCursorPositionChanged) { return; } UiDispatcher.BeginInvoke(new Action(() => { IKinectCursor[] cursorArray; lock (cursorDictionarySync) { cursorArray = cursorDictionary.Values.ToArray(); } foreach (var cursor in cursorArray) { cursor.SetPosition(normalizedX, normalizedY); } })); }
internal async override void InvokeAsync(JSMessage message) { switch (message.Method) { case "showAsGallery": object GalleryDetails = JsonConvert.DeserializeObject(message.Args[0].ToString()); ImageGalleryViewer gallery = new ImageGalleryViewer(GalleryDetails); UiDispatcher.BeginInvoke(() => { try { gallery.launchGallery(); } catch (Exception e) { Logger.Error(e.Message); } }); break; } }
// Invoked when app wakes from tombstone state async void HandleAppFromTombstoneAsync() { await Task.Run(() => { Dictionary <string, object> appData = MowblyClientManager.Instance.AppData; // Read the pages from applicationdata and load, if available if (appData.ContainsKey(KEY_PAGES)) { UiDispatcher.BeginInvoke(() => { try { // Get the pages Stack <PageModel> pageStack = JsonConvert.DeserializeObject <Stack <PageModel> >( (string)appData[KEY_PAGES]); // Restore the pages in UI foreach (PageModel page in pageStack) { PushPageModel(page, false); } // Add the activepage to view AddPageModelToView(activePage); } catch (Exception e) { Logger.Debug("Restore pages from tombstone failed. Reason - " + e.Message); Logger.Debug("Lauching default page..."); MowblyClientManager.Instance.LaunchDefaultPage(); } }); } }); }
/// <summary> /// Invokes an action asynchronously on the UI thread. /// </summary> /// <param name="action">The action that must be executed.</param> /// <returns> /// An object, which is returned immediately after BeginInvoke is called, that can be used to interact /// with the delegate as it is pending execution in the event queue. /// </returns> public static DispatcherOperation BeginInvoke(Action action) { CheckDispatcher(); return(UiDispatcher.BeginInvoke(action)); }
/// <summary> /// Invoke the method specified by the /// <see cref="CloudPact.MowblyFramework.Core.Features.JSMessage">JSMessage</see> object /// </summary> /// <param name="message"> /// <see cref="CloudPact.MowblyFramework.Core.Features.JSMessage">JSMessage</see> object /// </param> internal async override void InvokeAsync(JSMessage message) { switch (message.Method) { case "getPicture": int source = Convert.ToInt32(message.Args[0]); CameraOptions options = JsonConvert.DeserializeObject <CameraOptions>(message.Args[1].ToString()); string callbackId = message.CallbackId; try { if (source == (int)Camera.Source.CAMERA) { FilePath filePath = options.FilePath; bool isWriteToGallery = (filePath == null); } // Create the CameraTask CameraTask cameraTask; if (source == (int)Camera.Source.CAMERA) { Logger.Debug("Launching camera..."); cameraTask = new MowblyCameraCaptureTask(callbackId, options); } else { Logger.Debug("Launching photo chooser..."); cameraTask = new MowblyPhotoChooserTask(callbackId, options); } // Subscribe to CameraTask Completed event cameraTask.Completed += OnCameraTaskCompleted; // Show the CameraTask UiDispatcher.BeginInvoke(() => { cameraTask.Show(); }); // Make a note that app is navigated to external task Mowbly.AppNavigatedToExternalPage = true; } catch (Exception ce) { Logger.Error("Exception has occured. Reason - " + ce.Message); } break; case "getConfiguration": List <CameraConfig> cameraConfigList = await GetCameraConfigurations(); MethodResult result = cameraConfigList.Count > 0 ? new MethodResult { Result = cameraConfigList } : new MethodResult { Code = MethodResult.FAILURE_CODE, Error = new MethodError { Message = Mowbly.GetString(Constants.STRING_CAMERA_INITIALIZATION_ERROR) } }; InvokeCallbackJavascript(message.CallbackId, result); break; default: Logger.Error("Feature " + Name + " does not support method " + message.Method); break; } }
/// <summary> /// Invokes an action asynchronously on the UI thread. /// </summary> /// <param name="action">The action that must be executed.</param> /// <param name="priority"> /// The priority to use for the dispatcher call (defaults to /// <see cref="DispatcherPriority.Normal" />. /// </param> /// <returns> /// An object, which is returned immediately after BeginInvoke is called, that can be used to interact /// with the delegate as it is pending execution in the event queue. /// </returns> public static DispatcherOperation BeginInvoke(Action action, DispatcherPriority priority = DispatcherPriority.Normal) { CheckDispatcher(); return(UiDispatcher.BeginInvoke(action, priority)); }
private void FindAttachments(string path, Account a) { if (a.IsCategoryFund) { return; } HashSet <Transaction> set = new HashSet <Transaction>(); string accountDirectory = Path.Combine(path, NativeMethods.GetValidFileName(a.Name)); if (!string.IsNullOrEmpty(accountDirectory) && Directory.Exists(accountDirectory)) { foreach (string fileName in Directory.GetFiles(accountDirectory, "*.*")) { if (!threadRunning) { return; } string name = Path.GetFileName(fileName); int i = name.IndexOf("."); if (i > 0) { string s = name.Substring(0, i); long id = 0; if (long.TryParse(s, out id)) { Transaction t = this.money.Transactions.FindTransactionById(id); if (t != null) { set.Add(t); } } } } } // Updating Money transactions has to happen on the UI thread. UiDispatcher.BeginInvoke(new Action(() => { try { this.money.BeginUpdate(this); foreach (Transaction t in this.money.Transactions.GetTransactionsFrom(a)) { if (!threadRunning) { return; } if (t.HasAttachment && !set.Contains(t)) { t.HasAttachment = false; } if (!t.HasAttachment && set.Contains(t)) { t.HasAttachment = true; } } } finally { this.money.EndUpdate(); } })); }
void GetQuotes() { try { busy = true; hasError = false; errorLog = new StringBuilder(); newQuotes = XDocument.Parse("<StockQuotes/>"); int max = 0; List <Security> localCopy; lock (queue) { localCopy = new List <Security>(queue); max = localCopy.Count; queue.Clear(); } StringBuilder query = new StringBuilder(); string joiner = ""; int maxQuery = int.MaxValue; int count = 0; for (int i = 0; i < max; i++) { Security s = localCopy[i]; if (stop) { break; } try { string symbol = s.Symbol; if (!string.IsNullOrEmpty(symbol)) { if (symbol.IndexOfAny(illegalUrlChars) >= 0) { AddError(string.Format(Walkabout.Properties.Resources.SkippingSecurityIllegalSymbol, symbol)); } else { query.Append(joiner); query.Append(symbol); joiner = "+"; count++; } } else { AddError(string.Format(Walkabout.Properties.Resources.SkippingSecurityMissingSymbol, s.Name)); } if (count > maxQuery || i == max - 1) { FetchQuotesFromYahoo(query.ToString()); query = new StringBuilder(); } if (status != null) { status.ShowProgress(s.Name, 0, max, count); } } catch (System.Net.WebException we) { if (we.Status != WebExceptionStatus.RequestCanceled) { AddError(string.Format(Walkabout.Properties.Resources.ErrorFetchingSymbols, query.ToString()) + "\r\n" + we.Message); } else { // we cancelled, so bail. stop = true; break; } HttpWebResponse http = we.Response as HttpWebResponse; if (http != null) { // certain http error codes are fatal. switch (http.StatusCode) { case HttpStatusCode.ServiceUnavailable: case HttpStatusCode.InternalServerError: case HttpStatusCode.Unauthorized: AddError(http.StatusDescription); stop = true; break; } } } catch (Exception e) { XElement se = new XElement("Query", new XAttribute("Symbols", query.ToString())); se.Add(new XElement("Error", e.Message)); newQuotes.Root.Add(se); // continue AddError(string.Format(Walkabout.Properties.Resources.ErrorFetchingSymbols, query.ToString()) + "\r\n" + e.Message); } } if (!stop) { OnDownloadComplete(); } } catch (ThreadAbortException) { // shutting down. quotesThread = null; return; } catch (Exception e) { Debug.WriteLine(e.Message); } UiDispatcher.BeginInvoke(new Action(() => { // must run on the UI thread because some Money changed event handlers change dependency properties and that requires UI thread. ProcessResults(); })); this.quotesThread = null; }
/// <summary> /// Invoke the method specified by the /// <see cref="CloudPact.MowblyFramework.Core.Features.JSMessage">JSMessage</see> object /// </summary> /// <param name="message"> /// <see cref="CloudPact.MowblyFramework.Core.Features.JSMessage">JSMessage</see> object /// </param> internal async override void InvokeAsync(JSMessage message) { UiDispatcher.BeginInvoke(() => { switch (message.Method) { case "alert": if (activeControl == UiControl.None) { // Read args string alertOptionsStr = message.Args[0] as string; JObject alertOptions = JObject.Parse(alertOptionsStr); string alertTitle = (string)alertOptions[KEY_TITLE]; string alertMsg = (string)alertOptions[KEY_MESSAGE]; string alertCallbackId = (string)alertOptions[KEY_CALLBACK_ID]; // Create alert prompt MessagePrompt alertPrompt = new MessagePrompt(); alertPrompt.Title = alertTitle; alertPrompt.Message = alertMsg; // Subscribe to OnCompleted event EventHandler <PopUpEventArgs <string, PopUpResult> > onAlertPromptCompleted = null; onAlertPromptCompleted = (sender, e) => { // Set active control none if (activeControl != UiControl.Progress) { activeControl = UiControl.None; } prompt = null; UiDispatcher.BeginInvoke(() => { // Notify JS layer InvokeCallbackJavascript(alertCallbackId, new MethodResult()); // Unsubscrivbe from OnCompleted event alertPrompt.Completed -= onAlertPromptCompleted; }); }; alertPrompt.Completed += onAlertPromptCompleted; // Show the alert prompt alertPrompt.Show(); // Set active control activeControl = UiControl.Alert; prompt = alertPrompt; } break; case "confirm": if (activeControl == UiControl.None) { // Read args string confirmOptionsStr = message.Args[0] as string; JObject confirmOptions = JObject.Parse(confirmOptionsStr); List <Dictionary <string, string> > confirmButtons = confirmOptions["buttons"].ToObject <List <Dictionary <string, string> > >(); if (confirmButtons.Count >= 2) { string confirmTitle = (string)confirmOptions[KEY_TITLE]; string confirmMsg = (string)confirmOptions[KEY_MESSAGE]; string confirmCallbackId = (string)confirmOptions[KEY_CALLBACK_ID]; // Create confirm prompt MessagePrompt confirmPrompt = new MessagePrompt(); confirmPrompt.Title = confirmTitle; confirmPrompt.Message = confirmMsg; confirmPrompt.IsCancelVisible = true; // Subscribe to OnCompleted event // Required if the user cancels the confirm dialog using device back key press EventHandler <PopUpEventArgs <string, PopUpResult> > onConfirmPromptCompleted = null; onConfirmPromptCompleted = (sender, e) => { // Set active control none activeControl = UiControl.None; prompt = null; UiDispatcher.BeginInvoke(() => { // Notify JS layer InvokeCallbackJavascript(confirmCallbackId, -1); // Unsubscribe from OnCompleted event confirmPrompt.Completed -= onConfirmPromptCompleted; }); }; confirmPrompt.Completed += onConfirmPromptCompleted; // Function to return the button click handler encapsulating the index of the button Func <int, RoutedEventHandler> GetButtonClickHandler = (btnIndex) => { return(new RoutedEventHandler((o, args) => { // Unsubscribe from OnCompleted event // Not required as JS layer will be notified from here confirmPrompt.Completed -= onConfirmPromptCompleted; // Notify JS layer InvokeCallbackJavascript(confirmCallbackId, btnIndex); // Hide the confirm prompt confirmPrompt.Hide(); // Set active control none activeControl = UiControl.None; prompt = null; })); }; // Remove the default buttons confirmPrompt.ActionPopUpButtons.Clear(); // Create confirm buttons and add it to confirm prompt int index = 0; foreach (Dictionary <string, string> buttonDict in confirmButtons) { Button button = new Button { Content = buttonDict["label"] }; button.Click += GetButtonClickHandler(index); confirmPrompt.ActionPopUpButtons.Add(button); index++; } // Show the alert prompt confirmPrompt.Show(); // Set active control activeControl = UiControl.Confirm; prompt = confirmPrompt; } } break; case "hideProgress": if (activeControl == UiControl.Progress) { CloudPact.MowblyFramework.Core.Controls.ProgressOverlay.Instance.Hide(); // Set active control none activeControl = UiControl.None; } break; case "showProgress": if (activeControl != UiControl.Progress) { string progressMsg = message.Args[1] as string; CloudPact.MowblyFramework.Core.Controls.ProgressOverlay.Instance.Show(progressMsg); // Set active control activeControl = UiControl.Progress; } break; case "toast": if (activeControl == UiControl.None) { string toastMsg = message.Args[0] as string; int duration = DURATION_TOAST_LONG; if (message.Args.Length > 1) { duration = Convert.ToInt32(message.Args[1]); duration = (duration == 0) ? DURATION_TOAST_SHORT : DURATION_TOAST_LONG; } ToastPrompt toastPrompt = new ToastPrompt { Message = toastMsg, MillisecondsUntilHidden = duration }; toastPrompt.Show(); } break; default: Logger.Error("Feature " + Name + " does not support method " + message.Method); break; } }); await Task.FromResult(0); }