I'm having issues with the new SystemMediaTransportControls that replace MediaControl.
Currently, I have my app set up with:-
systemControls = SystemMediaTransportControls.GetForCurrentView();
systemControls.IsPlayEnabled = true;
systemControls.IsStopEnabled = true;
systemControls.IsPauseEnabled = true;
systemControls.ButtonPressed += SystemControls_ButtonPressed;
And
async void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
System.Diagnostics.Debug.WriteLine(args.Button);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
if (mediaElement1.CurrentState != MediaElementState.Playing)
{
restartSource();
}
else
{
completeClosure();
}
break;
case SystemMediaTransportControlsButton.Pause:
case SystemMediaTransportControlsButton.Stop:
completeClosure();
break;
default:
break;
}
});
}
And:
private async void completeClosure()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement1.Stop();
mediaElement1.Source = null;
timer.Stop();
});
}
private async void restartSource()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement1.Source = new Uri(holdThisSource, UriKind.Absolute);
mediaElement1.Play();
timer.Start();
});
}
When a user presses the Pause Button, args.Button shows up as "Play", hence the need for the checking for MediaElement's state. However, when I attempt to resume to media, it successfully resumes in restartSource() and updates the app accordingly but the icon on the Volume Control does not change from the Play sign, although hardware buttons still work.
Along with this, pressing the hardware Stop button NEVER works, and fails to even show up in Debug.WriteLine.
This is an online streaming app where the source does not allow resuming and thus I have to close the stream this way.
I'd love some help on this.
Since you did not update the systemControls.PlaybackStatus, the control button on transport control will not auto change to correct status.
You should always update the systemControls.PlaybackStatus property when the playback state has changed.
May this could solve your problems.
Related
I have a media podcast app built with xamarin forms and I am attempting to implement MediaManager's AudioFocus so my app can play well with other media apps. My main issue is being able to call RequestAudioFocus() when the user first clicks play and then also get the listener to work if another app starts playing media while my app is in the background. So both audios are not playing at the same time.
If I stick this code in MainActivity then the request works fine but also I don't really want the request to happen when the user opens the app. I want it to happen when the user clicks play.
I built a notification a while back that pops up a notification when the user first loads an episode that has a play/pause button in there as well that starts an activity to play/pause the episode. If I stick this code in that activity then everything works pretty well, even the listener in regard to other apps interfering. But again, I don't want to request audio focus only when they click the notification outside the app, I want it to start when they also click the play button inside the app.
So now I've built out another activity (different than the notification one). But I don't completely understand yet how to call this activity. If someone could point me in the right direction that would be great. I've been researching docs and other tutorials but I could use a nudge in the right direction. Thanks for your time.
One of the resources I am using can be found at https://www.sitepoint.com/managing-multiple-sound-sources-in-android-with-audio-focus/
This returns false every time. Doesn't get past the initialization of AudioManager.
public bool RequestAudioFocus()
{
AudioManager audioManager = (AudioManager)GetSystemService(AudioService);
AudioFocusRequest audioFocusRequest;
if (Build.VERSION.SdkInt > BuildVersionCodes.O)
{
audioFocusRequest = audioManager.RequestAudioFocus(new AudioFocusRequestClass.Builder(AudioFocus.Gain)
.SetAudioAttributes(new AudioAttributes.Builder().SetLegacyStreamType(Android.Media.Stream.Music).Build()).SetOnAudioFocusChangeListener(this)
.Build());
}
else
{
audioFocusRequest = audioManager.RequestAudioFocus(this, Android.Media.Stream.Music, AudioFocus.Gain);
}
if (audioFocusRequest == AudioFocusRequest.Granted)
{
return true;
}
return false;
}
public void Init(DabPlayer Player, bool IntegrateWithLockScreen)
{
dabplayer = Player;
var mSession = new MediaSessionCompat(Application.Context, "MusicService");
mSession.SetFlags(MediaSessionCompat.FlagHandlesMediaButtons | MediaSessionCompat.FlagHandlesTransportControls);
var controller = mSession.Controller;
var description = GlobalResources.playerPodcast;
if (IntegrateWithLockScreen)
{
/* SET UP LOCK SCREEN */
CreateNotificationChannel();
dabplayer.EpisodeDataChanged += (sender, e) =>
{
bool focus = RequestAudioFocus();
if (focus)
{
// Set up an intent so that tapping the notifications returns to this app:
Intent intent = new Intent(Application.Context, typeof(MainActivity));
Intent playPauseIntent = new Intent(Application.Context, typeof(SecondActivity));
//Intent audioFocusIntent = new Intent(Application.Context, typeof(AudioFocusActivity));
// Create a PendingIntent;
const int pendingIntentId = 0;
const int firstPendingIntentId = 1;
//const int audioFocusIntentId = 2;
//PendingIntent audioFocusPendingIntent =
// PendingIntent.GetActivity(Application.Context, audioFocusIntentId, audioFocusIntent, 0);
PendingIntent firstPendingIntent =
PendingIntent.GetActivity(Application.Context, firstPendingIntentId, intent, 0);
PendingIntent pendingIntent =
PendingIntent.GetActivity(Application.Context, pendingIntentId, playPauseIntent, 0);
// Build the notification:
var builder = new NotificationCompat.Builder(Application.Context, CHANNEL_ID)
.SetStyle(new Android.Support.V4.Media.App.NotificationCompat.MediaStyle()
.SetMediaSession(mSession.SessionToken)
.SetShowActionsInCompactView(0))
.SetVisibility(NotificationCompat.VisibilityPublic)
.SetContentIntent(firstPendingIntent) // Start up this activity when the user clicks the intent.
.SetDeleteIntent(MediaButtonReceiver.BuildMediaButtonPendingIntent(Application.Context, PlaybackState.ActionStop))
.SetSmallIcon(Resource.Drawable.app_icon) // This is the icon to display
.AddAction(Resource.Drawable.ic_media_play_pause, "Play", pendingIntent)
.SetContentText(GlobalResources.playerPodcast.EpisodeTitle)
.SetContentTitle(GlobalResources.playerPodcast.ChannelTitle);
// Finally, publish the notification:
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.Notify(NOTIFICATION_ID, builder.Build());
//StartActivity(audioFocusIntent); causes trying to invoke virtual method on
//null object reference when code and code above is uncommented
}
};
dabplayer.EpisodeProgressChanged += (object sender, EventArgs e) =>
{
};
}
}
This is the activity that was originally just supposed to be used for the notification area
[Activity]
public class SecondActivity : Activity, AudioManager.IOnAudioFocusChangeListener
{
DabPlayer player = GlobalResources.playerPodcast;
EpisodeViewModel Episode;
public bool RequestAudioFocus()
{
AudioManager audioManager = (AudioManager)GetSystemService(AudioService);
AudioFocusRequest audioFocusRequest;
if (Build.VERSION.SdkInt > BuildVersionCodes.O)
{
audioFocusRequest = audioManager.RequestAudioFocus(new AudioFocusRequestClass.Builder(AudioFocus.Gain)
.SetAudioAttributes(new AudioAttributes.Builder().SetLegacyStreamType(Android.Media.Stream.Music).Build()).SetOnAudioFocusChangeListener(this)
.Build());
}
else
{
audioFocusRequest = audioManager.RequestAudioFocus(this, Android.Media.Stream.Music, AudioFocus.Gain);
}
if (audioFocusRequest == AudioFocusRequest.Granted)
{
return true;
}
return false;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
switch (focusChange)
{
case AudioFocus.Gain:
player.Play();
//Gain when other Music Player app releases the audio service
break;
case AudioFocus.Loss:
//We have lost focus stop!
player.Stop();
break;
case AudioFocus.LossTransient:
//We have lost focus for a short time, but likely to resume so pause
player.Pause();
break;
case AudioFocus.LossTransientCanDuck:
//We have lost focus but should till play at a muted 10% volume
//player.SetVolume(.1);
break;
}
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
if (player.IsReady)
{
if (player.IsPlaying)
{
player.Pause();
}
else
{
if (RequestAudioFocus())
{
player.Play();
}
}
}
else
{
if (player.Load(Episode.Episode))
{
if (RequestAudioFocus())
{
player.Play();
}
}
else
{
//DisplayAlert("Episode Unavailable", "The episode you are attempting to play is currently unavailable. Please try again later.", "OK");
}
}
Finish();
}
}
This is the new activity I built and hoping to use when the user interacts with the player but I'm not sure how to call/implement it.
[Activity]
public class AudioFocusActivity : Activity, AudioManager.IOnAudioFocusChangeListener
{
DabPlayer player = GlobalResources.playerPodcast;
DroidDabNativePlayer droid = new DroidDabNativePlayer();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
RequestAudioFocus();
}
public bool RequestAudioFocus()
{
AudioManager audioManager = (AudioManager)GetSystemService(AudioService);
AudioFocusRequest audioFocusRequest;
if (Build.VERSION.SdkInt > BuildVersionCodes.O)
{
audioFocusRequest = audioManager.RequestAudioFocus(new AudioFocusRequestClass.Builder(AudioFocus.Gain)
.SetAudioAttributes(new AudioAttributes.Builder().SetLegacyStreamType(Android.Media.Stream.Music).Build()).SetOnAudioFocusChangeListener(this)
.Build());
}
else
{
audioFocusRequest = audioManager.RequestAudioFocus(this, Android.Media.Stream.Music, AudioFocus.Gain);
}
if (audioFocusRequest == AudioFocusRequest.Granted)
{
return true;
}
return false;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
switch (focusChange)
{
case AudioFocus.Gain:
player.Play();
//Gain when other Music Player app releases the audio service
break;
case AudioFocus.Loss:
//We have lost focus stop!
player.Stop();
break;
case AudioFocus.LossTransient:
//We have lost focus for a short time, but likely to resume so pause
player.Pause();
break;
case AudioFocus.LossTransientCanDuck:
//We have lost focus but should till play at a muted 10% volume
//player.SetVolume(.1);
break;
}
}
}
This is just my play method in my androidplayer class
/// Begin playback or resume if paused
public void Play()
{
if (player == null)
return;
if (IsPlaying)
{
//Go back to the beginning (don't start playing)... not sure what this is here for if if it ever gets hit.
Pause();
Seek(0);
}
else if (player.CurrentPosition >= player.Duration)
{
//Start over from the beginning if at the end of the file
player.Pause();
Seek(0);
}
else
{
//Play from where we're at
}
player.Start();
}
If I were you I would put both your Audio Focus code and your Audio Player code in a ForegroundService and not the Activity, this way you can navigate to different activities, without interrupting Audio Playback. You will need to do something like that anyways if you want playback when the App is in the background.
Implementing a ForegroundService will also let you add buttons to your notification or if you are using one of the rich Audio Notification, then you can send intents directly to your ForegroundService from the buttons on the notification, rather than having to open up your App. So for your pending intents you could communicate directly with the service instead.
Also when requesting audio focus, you need to respect whether the audio focus was granted or not. Right now you are just requesting it and throwing away the result. Only if the focus was granted you should start playing back the audio.
So I'm new in programming with Xamarin (actually even with C# tbh)
What I'm trying to acheave is a Task which should only work when a Switch (called S1) is Toggled.
My idea:
public async Task GetCon(){
for (; ; )
{
if (S1.IsToggled == true)
{
AI1.IsRunning = true;
bool CStat = await CrossConnectivity.Current.IsRemoteReachable("https://www.google.ch");
if (CStat == true)
{
StatLbl.Text = "Online";
}
else if (CStat == false)
{
StatLbl.Text = "Offline";
break;
}
off:;
await Task.Delay(3000);
}
All works fine but if I turn the Switch back off and make google unreachable, the StatLbl text doesn't change to offline.
Any idea?
As you're new to C#, I'm surprised no-one else has picked up on this, but here goes.
Instead of infinitely running a Task and waiting for the switch to be toggled, use the Toggled event to trigger when the toggle status changes. How does it work? When you toggle the switch, your program will automatically call that method. For example:
public MyConstructor()
{
S1.Toggled += S1_Toggled;
}
void S1_Toggled(object sender, ToggledEventArgs e)
{
System.Diagnostics.Debug.WriteLine(String.Format("Switch is now {0}", e.Value));
}
You can find more information (and some example) for the Switch at the Xamarin Forms Docs.
As Jason pointed out, you should be modifying UI properties from the UI thread. Properties like colour, visibility, text etc (anything that changes on the display) should be done in Device.BeginInvokeOnMainThread like so:
Device.BeginInvokeOnMainThread(() =>
{
StatLbl.Text = "Offline";
});
you need to execute UI changes on the UI thread
Device.BeginInvokeOnMainThread(() => {
StatLbl.Text = "Offline";
});
Most of the code executes only when the switch is on, you have this line that prevents from changing the label name when the switch is on:
if (S1.IsToggled == true)
I have recently decided to add Background Audio playback support for podcasts in my app. I have got most of it to work but, the pause button in the SystemTransportControls of the BackgroundMediaPlayer doesn't seem to do anything.
Here is my background audio task class file:
public sealed class AudioPlayer : IBackgroundTask
{
private BackgroundTaskDeferral _deferral;
public void Run(IBackgroundTaskInstance taskInstance)
{
_deferral = taskInstance.GetDeferral();
var control = BackgroundMediaPlayer.Current.SystemMediaTransportControls;
control.IsEnabled = true;
control.IsPauseEnabled = true;
control.IsPlayEnabled = true;
control.IsNextEnabled = false;
control.IsPreviousEnabled = false;
taskInstance.Canceled += TaskInstance_Canceled;
BackgroundMediaPlayer.MessageReceivedFromForeground += BackgroundMediaPlayer_MessageReceivedFromForeground;
}
private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
BackgroundMediaPlayer.Shutdown();
_deferral.Complete();
}
void BackgroundMediaPlayer_MessageReceivedFromForeground(object sender, MediaPlayerDataReceivedEventArgs e)
{
object obj;
e.Data.TryGetValue("MessageBody", out obj);
string url = (string)obj;
url = url.Replace("\"", "");
var source = MediaSource.CreateFromUri(new Uri(url, UriKind.Absolute));
var list = new MediaPlaybackList();
list.Items.Add(new MediaPlaybackItem(source));
BackgroundMediaPlayer.Current.Source = list;
BackgroundMediaPlayer.Current.Play();
}
}
It is important to note that the audio does start playing in the background but I don't have the ability to pause the audio.
Thanks,
P.
To react to SystemMediaTransportControls (SMTC) and handle each Universal Volume Control (UVC) button: play, pause, next, and previous, we need handle the SystemMediaTransportControls.ButtonPressed event in Run method like following:
public void Run(IBackgroundTaskInstance taskInstance)
{
var control = BackgroundMediaPlayer.Current.SystemMediaTransportControls;
control.ButtonPressed += control_ButtonPressed;
...
}
And in control_ButtonPressed method, deal with different buttons like:
private void control_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
//Todo with play
break;
case SystemMediaTransportControlsButton.Pause:
//Todo with pause
break;
case SystemMediaTransportControlsButton.Next:
//Todo with skip to next;
break;
case SystemMediaTransportControlsButton.Previous:
//Todo with skip to previous;
break;
}
}
For a complete sample, please refer to the official Background audio sample on GitHub, especially the MyBackgroundAudioTask class. And there is also a very nice post that will walk you through setting up background audio, reacting to device media controls, communicating with the background media player, and managing playlists. Read more at The Basics of Background Audio.
I am working on my Project (a soundcloud client) and the app can play tracks just fine, but not when the app is minimized. I use the MediaElement-Object for playing the mp3 from the url. How can i force the music to continue playing the music, when the app is in the background. Or whats the easiest way/best explained tutorial to implement this. I searched alot for a good answer, but the ones, i found, was too good for me :D What means, that i didn't understand it.
To play audio in the background you will have to do a Declaration in Package.appxmanifest for a Background Tasks, enable audio and add an entry point like TestUWP.MainPage page.
Also for the user to easily be able to manage the audio you can use SystemMediaTransportControls
Here is a basic setup with Play and Pause.
xaml
<MediaElement x:Name="mediaElement" Height="100" Width="100" AreTransportControlsEnabled="True"/>
C#
public MainPage()
{
this.InitializeComponent();
systemControls = SystemMediaTransportControls.GetForCurrentView();
// Register to handle the following system transpot control buttons.
systemControls.ButtonPressed += SystemControls_ButtonPressed;
mediaElement.CurrentStateChanged += MediaElement_CurrentStateChanged;
systemControls.IsPlayEnabled = true;
systemControls.IsPauseEnabled = true;
}
private void MediaElement_CurrentStateChanged(object sender, RoutedEventArgs e)
{
switch (mediaElement.CurrentState)
{
case MediaElementState.Playing:
systemControls.PlaybackStatus = MediaPlaybackStatus.Playing;
break;
case MediaElementState.Paused:
systemControls.PlaybackStatus = MediaPlaybackStatus.Paused;
break;
case MediaElementState.Stopped:
systemControls.PlaybackStatus = MediaPlaybackStatus.Stopped;
break;
case MediaElementState.Closed:
systemControls.PlaybackStatus = MediaPlaybackStatus.Closed;
break;
default:
break;
}
}
void SystemControls_ButtonPressed(SystemMediaTransportControls sender, SystemMediaTransportControlsButtonPressedEventArgs args)
{
switch (args.Button)
{
case SystemMediaTransportControlsButton.Play:
PlayMedia();
break;
case SystemMediaTransportControlsButton.Pause:
PauseMedia();
break;
case SystemMediaTransportControlsButton.Stop:
StopMedia();
break;
default:
break;
}
}
private async void StopMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Stop();
});
}
async void PlayMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (mediaElement.CurrentState == MediaElementState.Playing)
mediaElement.Pause();
else
mediaElement.Play();
});
}
async void PauseMedia()
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
mediaElement.Pause();
});
}
Output
If you like to enable more controls you can do using the available properties for ex.
systemControls.IsNextEnabled = true;
and you have to add the case in the button switch.
case SystemMediaTransportControlsButton.Next:
//handle next song
break;
Individually, all code works perfectly. The snippet for saving the file, the snippet for picking a directory to save it to and also the message dialog works great.
But when I tie it all together, I get an access denied. I am not using the DocumentsLibrary capability since it is not required of me to do so in this case, however, enabling this capability after running into issues confirmed that it is not the issue.
Scenario:
User wants to create a new document after entering text in the text box. A MessageDialog appears, asking them if they want to save changes to the existing file first - the user clicks Yes (save file).
Now, here is where you handle the event that was raised by the MessageDialog.
Inside the IUICommand command event handler, you test for which button was clicked, and act accordingly.
I did this with a switch statement:
switch(command.Label) {
case "Yes":
SaveFile(); // extension method containing save file code that works on its own
break;
case "No":
ClearDocument();
break;
default:
break;
}
Now, each case works great except for the Yes button. When you click yes, an e tension method is called which has code that saves to a file
It is when you click yes button that you get the ACCESS DENIED exception. Details of the exception didn't reveal anything.
I think that it has something to do with how I am using the MesaageDialog. But after searching for hours I have yet to find a sample on how to save a file with the FileSavePicker when a MesaageDialog button is pressed.
Any ideas in how this should be done?
Update w/ Code
When the user clicks the New document button on the AppBar, this method fires:
async private void New_Click(object sender, RoutedEventArgs e)
{
if (NoteHasChanged)
{
// Prompt to save changed before closing the file and creating a new one.
if (!HasEverBeenSaved)
{
MessageDialog dialog = new MessageDialog("Do you want to save this file before creating a new one?",
"Confirmation");
dialog.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(this.CommandInvokedHandler)));
dialog.Commands.Add(new UICommand("No", new UICommandInvokedHandler(this.CommandInvokedHandler)));
dialog.Commands.Add(new UICommand("Cancel", new UICommandInvokedHandler(this.CommandInvokedHandler)));
dialog.DefaultCommandIndex = 0;
dialog.CancelCommandIndex = 2;
// Show it.
await dialog.ShowAsync();
}
else { }
}
else
{
// Discard changes and create a new file.
RESET();
}
}
And the FileSavePicker stuff:
private void CommandInvokedHandler(IUICommand command)
{
// Display message showing the label of the command that was invoked
switch (command.Label)
{
case "Yes":
MainPage rootPage = this;
if (rootPage.EnsureUnsnapped())
{
// Yes was chosen. Save the file.
SaveNewFileAs();
}
break;
case "No":
RESET(); // Done.
break;
default:
// Not sure what to do, here.
break;
}
}
async public void SaveNewFileAs()
{
try
{
FileSavePicker saver = new FileSavePicker();
saver.SuggestedStartLocation = PickerLocationId.Desktop;
saver.CommitButtonText = "Save";
saver.DefaultFileExtension = ".txt";
saver.FileTypeChoices.Add("Plain Text", new List<String>() { ".txt" });
saver.SuggestedFileName = noteTitle.Text;
StorageFile file = await saver.PickSaveFileAsync();
thisFile = file;
if (file != null)
{
CachedFileManager.DeferUpdates(thisFile);
await FileIO.WriteTextAsync(thisFile, theNote.Text);
FileUpdateStatus fus = await CachedFileManager.CompleteUpdatesAsync(thisFile);
//if (fus == FileUpdateStatus.Complete)
// value = true;
//else
// value = false;
}
else
{
// Operation cancelled.
}
}
catch (Exception exception)
{
Debug.WriteLine(exception.InnerException);
}
}
Any progress on this issue? I currently have the same problem. I have also found that the same problem occurs if a second MessageDialog is shown in the IUICommand event.
My solution is to cancel the first operation (that shows the first message dialog). Here some code I’m using (it’s accessible in a global object):
private IAsyncInfo mActiveDialogOperation = null;
private object mOperationMutex = new object();
private void ClearActiveOperation(IAsyncInfo operation)
{
lock (mOperationMutex)
{
if (mActiveDialogOperation == operation)
mActiveDialogOperation = null;
}
}
private void SetActiveOperation(IAsyncInfo operation)
{
lock (mOperationMutex)
{
if (mActiveDialogOperation != null)
{
mActiveDialogOperation.Cancel();
}
mActiveDialogOperation = operation;
}
}
public void StopActiveOperations()
{
SetActiveOperation(null);
}
public async void ShowDialog(MessageDialog dialog)
{
StopActiveOperations();
try
{
IAsyncOperation<IUICommand> newOperation = dialog.ShowAsync();
SetActiveOperation(newOperation);
await newOperation;
ClearActiveOperation(newOperation);
}
catch (System.Threading.Tasks.TaskCanceledException e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
}
So every time I want to show a MessageDialog I call ShowDialog. This will cancel the current dialog if any (then a TaskCanceledException occurs).
In the case when I will use a FileSavePicker, I call StopActiveOperations before PickSaveFileAsync is called.
This works but I can’t say I like it. It feels like I’m doing something wrong.
OK, now I have figured it out :-). The documentation says explicit that you shouldn’t show new popups/file pickers in the UICommand:
http://msdn.microsoft.com/en-US/library/windows/apps/windows.ui.popups.messagedialog.showasync
This is an example of a bad way to do it:
private async void Button_Click(object sender, RoutedEventArgs e)
{
MessageDialog dialog = new MessageDialog("Press ok to show new dialog (the application will crash).");
dialog.Commands.Add(new UICommand("OK", new UICommandInvokedHandler(OnDialogOkTest1)));
dialog.Commands.Add(new UICommand("Cancel"));
await dialog.ShowAsync();
}
private async void OnDialogOkTest1(IUICommand command)
{
MessageDialog secondDialog = new MessageDialog("This is the second dialog");
secondDialog.Commands.Add(new UICommand("OK"));
await secondDialog.ShowAsync();
}
This is the correct way to do it:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
MessageDialog dialog = new MessageDialog("Press ok to show new dialog");
UICommand okCommand = new UICommand("OK");
UICommand cancelCommand = new UICommand("Cancel");
dialog.Commands.Add(okCommand);
dialog.Commands.Add(cancelCommand);
IUICommand response = await dialog.ShowAsync();
if( response == okCommand )
{
MessageDialog secondDialog = new MessageDialog("This is the second dialog");
secondDialog.Commands.Add(new UICommand("OK"));
await secondDialog.ShowAsync();
}
}
Quite simple actually, I should have get this earlier...