“对话框必须由用户启动。”使用Silverlight 3中的SaveFileDialog

我正在使用C#开发Silverlight 3应用程序。 我想允许用户从Silverlight应用程序下载图像。 我正在使用SaveFileDialog来执行文件下载任务。 流程就是这样:

  1. 用户单击SL应用程序中的“下载”按钮。
  2. 调用Web服务调用以从服务器获取映像
  3. 调用Web方法调用的OnCompleted异步事件处理程序并从服务器接收二进制映像
  4. 在OnCompleted事件处理程序中,SaveFileDialog提示用户将图像保存到计算机。
  5. 将图像流式传输到用户硬盘上的文件。

我在一个函数中使用以下代码,该函数从OnCompleted事件处理程序调用,以完成SaveFileDialog提示,然后流式传输到文件。

SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "JPG Files|*.jpg" + "|All Files|*.*"; bool? dialogResult = dialog.ShowDialog(); if (dialogResult == true) { using (Stream fs = (Stream)dialog.OpenFile()) { fs.Write(e.Result, 0, e.Result.Length); fs.Close(); } } 

SaveFileDialog会抛出错误“对话必须是用户启动的”。 在上面的代码中调用ShowDialog方法时。 我能在这里找到什么? 怎么克服这个?

此错误消息的含义是您只能显示SaveFileDialog以响应用户启动的事件,例如单击按钮。 在您描述的示例中,您没有显示SaveFileDialog以响应单击,而是响应已完成的http请求(不被视为用户启动的事件)。 因此,要使其工作,您需要做的是,在http请求的Completed事件中,向用户显示一些UI,说“下载已完成,单击此处将文件保存到您的计算机”,以及当用户点击时在此消息上,显示SaveFileDialog。

在下载之前先问一下怎么样? 它似乎从错误消息中建议,这是Silverlight希望您提示确保它知道用户请求操作的方式,而不是您使用弹出窗口向用户进行spaming。

除了Silverlight安全模型之外,我宁愿不等待下载完成之后再被问到放在哪里!

正如基思所说,这是设计的。 本教程使用代码提供了一个很好的示例,我用它以“正确”的方式从服务器下载文件。 (也适用于Silverlight 4)

我刚开始使用Silverlight 4并遇到了同样的问题。 似乎如果您手动创建事件处理程序,则抛出安全性exception,即使事件处理程序正在处理具有正确参数的按钮单击事件,但是如果您在Xaml中的按钮上使用“创建新事件处理程序”选项在click事件下,新的事件处理程序,具有相同的代码和参数现在可以工作….这是我从开始从WPF过渡到Silverlight后遇到的许多“corky”事件之一。

 Private _syncContext As SynchronizationContext Private mBigStream As Stream Private Sub btnSave_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnSave.Click Try Dim saveDialog As New SaveFileDialog saveDialog.Filter = "Word |*.doc" saveDialog.DefaultExt = ".doc" If saveDialog.ShowDialog() Then Try mBigStream = saveDialog.OpenFile() _syncContext = SynchronizationContext.Current oWebService.GetReportAsync(Params, ... , _syncContext) Catch ex As Exception MessageBox.Show("File busy.") End Try End If Catch ex As Exception LogError((New System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name.ToString, Err.Description) End Try End Sub Private Sub oWebService_GetReportCompleted(sender As Object, e As MainReference.GetReportCompletedEventArgs) Handles oWebService.GetReportCompleted Try ' e.Result is byte() If e.Result IsNot Nothing Then If e.Result.Count > 0 Then _syncContext.Post(Sub() Try mBigStream.Write(e.Result, 0, e.Result.Length) mBigStream.Flush() mBigStream.Close() mBigStream.Dispose() mBigStream = Nothing Catch ex As Exception LogError((New System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name.ToString, Err.Description) End Try End Sub, Nothing) _syncContext = Nothing End If End If Catch ex As Exception LogError((New System.Diagnostics.StackTrace()).GetFrame(0).GetMethod().Name.ToString, Err.Description) End Try End Sub