C# “对话必须由用户发起。” 在 Silverlight 3 中使用 SaveFileDialog

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1355078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:32:46  来源:igfitidea点击:

"Dialogs must be user-initiated." with SaveFileDialog in Silverlight 3

c#.netsilverlight-3.0

提问by pencilslate

I am working on a Silverlight 3 app with C#. I would like to allow the user to download an image from the Silverlight app. I am using SaveFileDialog to perform the file download task. The flow goes this way:

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

  1. User clicks on Download button in the SL app.
  2. Web service call invoked to get the image from server
  3. OnCompleted async event handler of the web method call get invoked and receives the binary image from the server
  4. Within the OnCompleted event handler, SaveFileDialog prompted to user for saving the image to computer.
  5. Stream the image to the file on user's harddrive.
  1. 用户单击 SL 应用程序中的下载按钮。
  2. 调用 Web 服务调用以从服务器获取图像
  3. 调用 Web 方法调用的 OnCompleted 异步事件处理程序并从服务器接收二进制图像
  4. 在 OnCompleted 事件处理程序中,SaveFileDialog 提示用户将图像保存到计算机。
  5. 将图像流式传输到用户硬盘上的文件。

I am using the following code in a function which is called from the OnCompleted event handler to accomplish SaveFileDialog prompt and then streaming to file.

我在从 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();
                }
            }

The SaveFileDialog would throw the error "Dialogs must be user-initiated." when invoking ShowDialog method in the above code. What could i be missing here? How to overcome this?

SaveFileDialog 会抛出错误“对话框必须由用户启动”。在上面的代码中调用 ShowDialog 方法时。我会在这里错过什么?如何克服这一点?

采纳答案by KeithMahoney

What this error message means is that you can only show a SaveFileDialog in response to a user initiated event, such as a button click. In the example you describe, you are not showing SaveFileDialog in response to a click, but rather in response to a completed http request (which is not considered a user initiated event). So, what you need to do to get this to work is, in the Completed event of the http request, show some UI to the user saying "download completed, click here to save the file to your computer", and when the user clicks on this message, display the SaveFileDialog.

此错误消息意味着您只能显示 SaveFileDialog 以响应用户启动的事件,例如按钮单击。在您描述的示例中,您没有显示 SaveFileDialog 以响应单击,而是响应已完成的 http 请求(这不被视为用户发起的事件)。所以,你需要做的是让这个工作是,在 http 请求的 Completed 事件中,向用户显示一些 UI 说“下载完成,点击这里将文件保存到你的电脑”,当用户点击在此消息上,显示 SaveFileDialog。

回答by Ray Hayes

How about asking first, before downloading? It seems to suggest from the error message that it is the way Silverlight wants you to prompt to ensure it knows a user requested the action, not you spaming the user with popups.

下载前先问一下怎么样?似乎从错误消息中可以看出 Silverlight 希望您以这种方式提示以确保它知道用户请求了该操作,而不是您通过弹出窗口向用户发送垃圾邮件。

Silverlight security model aside, I'd rather not wait for a download to finish before being asked where to put it!

撇开 Silverlight 安全模型不谈,我宁愿不等待下载完成才被问到把它放在哪里!

回答by JumpingJezza

As Keith mentioned this is by design. Thistutorial gives an excellent example using code which I used to download a file from the server in the "correct" way. (Works in Silverlight 4 too)

正如基思所提到的,这是设计使然。教程提供了一个使用代码的优秀示例,我曾经使用该代码以“正确”的方式从服务器下载文件。(也适用于 Silverlight 4)

回答by Greg S

I just started on Silverlight 4 and had the same issue. It seems that if you manually create event handlers, the security exception is thrown, even if the event handler is handling a button click event with the correct parameters, but if you use the "create a new event handler" option on the button in Xaml under the click event, the new event handler, with the same code and parameters now works....this is one of the many "corky" things that I have come across since starting the transition from WPF to Silverlight.

我刚开始使用 Silverlight 4 并遇到了同样的问题。似乎如果您手动创建事件处理程序,即使事件处理程序正在使用正确的参数处理按钮单击事件,也会引发安全异常,但是如果您在 Xaml 中的按钮上使用“创建新的事件处理程序”选项在单击事件下,具有相同代码和参数的新事件处理程序现在可以工作了……这是我从 WPF 开始过渡到 Silverlight 以来遇到的许多“软木塞”的事情之一。

回答by Alex

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