使用带有MessageDialog's iuiccommand事件的FileSavePicker
本文关键字:iuiccommand 事件 FileSavePicker MessageDialog | 更新日期: 2023-09-27 17:50:51
单独来看,所有代码都能完美地工作。用于保存文件的代码段,用于选择保存目录的代码段以及消息对话框都工作得很好。
但是当我把它们连接在一起时,我得到了一个访问被拒绝。我没有使用documentlibrary功能,因为在这种情况下我不需要这样做,但是,在遇到问题后启用此功能确认这不是问题。
场景:用户希望在文本框中输入文本后创建新文档。出现一个MessageDialog
,询问他们是否要先保存对现有文件的更改-用户单击Yes (save file)。
现在,这里是您处理由MessageDialog
引发的事件的地方。
在IUICommand命令事件处理程序中,您将测试单击了哪个按钮,并采取相应的操作。
我使用了一个switch语句:
switch(command.Label) {
case "Yes":
SaveFile(); // extension method containing save file code that works on its own
break;
case "No":
ClearDocument();
break;
default:
break;
}
现在,除了Yes按钮之外,每个case都工作得很好。当单击yes时,将调用一个张力方法,该方法包含保存到文件
的代码。当您单击yes按钮时,您将获得ACCESS DENIED异常。异常的细节没有透露任何东西。
我认为这与我如何使用MesaageDialog
有关。但是在搜索了几个小时之后,我还没有找到一个关于如何在按下MesaageDialog
按钮时保存FileSavePicker
文件的示例。
有什么好主意吗?
更新w/Code
当用户点击AppBar上的新建文档按钮时,这个方法被触发:
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();
}
}
和FileSavePicker的东西:
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);
}
}
这个问题有进展吗?我现在也有同样的问题。我还发现,如果在IUICommand
事件中显示第二个MessageDialog
,则会出现同样的问题。
我的解决方案是取消第一个操作(显示第一个消息对话框)。下面是我使用的一些代码(它可以在全局对象中访问):
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);
}
}
所以每次我想显示一个MessageDialog时,我调用ShowDialog。这将取消当前对话框,如果有的话(然后发生TaskCanceledException)。
在这种情况下,我将使用一个FileSavePicker,我调用StopActiveOperations之前PickSaveFileAsync被调用。
这个工作,但我不能说我喜欢它。感觉好像我做错了什么。
好了,现在我明白了:-)。文档明确指出,不应该在ui命令
中显示新的弹出窗口/文件选择器。http://msdn.microsoft.com/en-US/library/windows/apps/windows.ui.popups.messagedialog.showasync这是一个坏的方式的例子:
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();
}
正确的做法是:
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();
}
}
其实很简单,我应该早点知道的。