【问题标题】:"Dialogs must be user-initiated." with SaveFileDialog in Silverlight 3“对话必须由用户启动。”在 Silverlight 3 中使用 SaveFileDialog
【发布时间】:2009-08-30 22:25:31
【问题描述】:

我正在使用 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 方法时。我可能在这里缺少什么?如何克服?

【问题讨论】:

    标签: c# .net silverlight-3.0


    【解决方案1】:

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

    【讨论】:

    • 我在尝试直接从 Button_Click 事件处理程序中使用 SaveFileDialog 时收到相同的错误消息,因为我在调用 new SaveFileDialog() 之前在该方法中进行了一些验证。下面 JumpingJezza 的链接显示了一个很好的示例,但似乎关键是将 new SaveFileDialog() 作为按钮事件处理程序中的 first 行。在那之后,你似乎可以做任何你喜欢的事情。
    • 而“第一”行真正的意思是第一。我正在调试其他人的代码,并且按钮单击事件处理程序中的注释代码块导致了上述异常。
    • 我认为这是打开保存对话框之前的时间问题。如果您在 dialog.ShowDialog() 错误发生之前放置断点。见dotnetslang.wordpress.com/2011/03/12/…
    【解决方案2】:

    在下载之前先询问如何?错误消息似乎表明这是 Silverlight 希望您提示以确保它知道用户请求该操作的方式,而不是您通过弹出窗口向用户发送垃圾邮件。

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 您也可以在按钮事件处理程序中创建 SaveFileDialog。关键是要确保构造函数是方法的第一行。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:
        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
        

        【讨论】:

        • 您能否更详细地解释您的答案?答案应该提供方向,而不仅仅是 c/p 代码。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多