I have a Windows 8 Metro style app and I have run into what should be a simple thing to accomplish, but am finding it extremely difficult to come up with a solution. As it’s been a week now and I still haven’t found a solution, I am offering a bounty of 300 rep for a working solution.
Scenario:
When I edit a textbox, and click Create New Document, a MessageDialog appears asking if I want to save changes to the existing file before creating a new one. If I click “Yes, save changes” – then the FileSavePicker opens, allowing me to save the file.
The Problem:
When I click “Yes, save changes”, I get an ACCESSDENIED exception. I have set breakpoints but exception details have not revealed any other information.
Notes:
I do not have DocumentsLibrary declaration enabled because in this case that is not a requirement, and when this did not work, I then tried enabling it anyway – and I still got the error.
Also, all pieces of code work perfectly on their own (separate from each other), but when you tie it all together, it falls apart when the FileSavePicker tried to open.
I believe this may be a Threading issue. But I’m not sure.
MessageDialog on MSDN.
The code I have is below:
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);
}
}
How can I get this to work?
The problem seems to be that you’re opening a
FileSavePickerbefore theMessageDialogis closed (and before theawait dialog.ShowAsync()call is terminated). I am not sure of why this behavior happens, but a workaround can be easily done. I’ll only make an example, it will be up to you to adapt it to your needs and model.First, declare an
Enum.Then, create a field/property in your class. Again, this is not the most wise design choice but it works as an example.
Then, modify your
CommandInvokeHandlermethod:Finally, edit your
New_Clickmethod: