«Диалоги должны быть инициированы пользователем». с помощью SaveFileDialog в Silverlight 3 - PullRequest
18 голосов
/ 31 августа 2009

Я работаю над приложением Silverlight 3 с C #. Я хотел бы разрешить пользователю загружать изображения из приложения Silverlight. Я использую SaveFileDialog для выполнения задачи загрузки файла. Поток идет следующим образом:

  1. Пользователь нажимает кнопку «Загрузить» в приложении SL.
  2. вызов веб-службы для получения изображения с сервера
  3. 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 в приведенном выше коде. Чего мне здесь не хватает? Как это побороть?

Ответы [ 5 ]

20 голосов
/ 31 августа 2009

Это сообщение об ошибке означает, что вы можете показывать SaveFileDialog только в ответ на инициированное пользователем событие, такое как нажатие кнопки. В описываемом примере вы не показываете SaveFileDialog в ответ на щелчок, а скорее в ответ на завершенный http-запрос (который не считается событием, инициированным пользователем). Итак, что вам нужно сделать, чтобы заставить это работать, в событии «Завершено» http-запроса показать пользователю некоторый пользовательский интерфейс: «загрузка завершена, нажмите здесь, чтобы сохранить файл на свой компьютер», и когда пользователь нажимает в этом сообщении отобразите SaveFileDialog.

5 голосов
/ 31 августа 2009

Как насчет того, чтобы спросить перед загрузкой? Из сообщения об ошибке кажется, что Silverlight хочет, чтобы вы запрашивали, чтобы он знал, что пользователь запросил действие, а не спамит пользователя всплывающими окнами.

За исключением модели безопасности Silverlight, я бы предпочел не ждать окончания загрузки, прежде чем спросить, где ее разместить!

1 голос
/ 06 ноября 2012
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
1 голос
/ 06 января 2011

Я только начал работать с Silverlight 4, и у меня возникла та же проблема. Кажется, что если вы вручную создаете обработчики событий, возникает исключение безопасности, даже если обработчик событий обрабатывает событие нажатия кнопки с правильными параметрами, но если вы используете опцию «создать новый обработчик события» для кнопки в Xaml под событием click теперь работает новый обработчик событий с тем же кодом и параметрами .... это одна из многих "хитрых" вещей, с которыми я столкнулся после начала перехода с WPF на Silverlight.

1 голос
/ 08 декабря 2010

Как упомянул Кит, это сделано по замыслу. В этом руководстве приведен отличный пример использования кода, который я использовал для загрузки файла с сервера «правильным» способом. (Работает и в Silverlight 4)

...