"Диалоги должны быть инициированы пользователем". с SaveFileDialog в Silverlight 3
Я работаю над приложением Silverlight 3 с С#. Я хотел бы разрешить пользователю загружать изображение из приложения Silverlight. Я использую SaveFileDialog для выполнения задачи загрузки файлов. Поток идет следующим образом:
- Пользователь нажимает кнопку Загрузить в приложении SL.
- Вызов службы веб-сервиса для получения изображения с сервера
- OnCompleted обработчик события async вызова метода веб-вызова get вызывается и получает двоичное изображение с сервера
- В обработчике событий OnCompleted SaveFileDialog запрашивает у пользователя сохранение изображения на компьютере.
- Поток изображения в файл на жестком диске пользователя.
Я использую следующий код в функции, которая вызывается из обработчика события 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 в приведенном выше коде. Что я могу здесь пропустить? Как преодолеть это?
Ответы
Ответ 1
Это сообщение об ошибке означает, что вы можете показывать только SaveFileDialog в ответ на инициированное пользователем событие, такое как щелчок на кнопке. В примере, который вы описываете, вы не показываете SaveFileDialog в ответ на клик, а скорее в ответ на завершенный HTTP-запрос (который не считается инициированным пользователем событием). Итак, что вам нужно сделать, чтобы заставить это работать, в событии Completed http-запроса отобразить некоторый пользовательский интерфейс для пользователя, говорящего: "загрузка завершена, нажмите здесь, чтобы сохранить файл на вашем компьютере", и когда пользователь нажимает в этом сообщении отобразите SaveFileDialog.
Ответ 2
Как насчет запроса во-первых, перед загрузкой? Похоже, из сообщения об ошибке следует, что Silverlight хочет, чтобы вы предложили, чтобы он знал, что пользователь запросил действие, а не вы проклинали пользователя всплывающими сообщениями.
Модель безопасности Silverlight в сторону, я бы предпочел не дождаться завершения загрузки, прежде чем ее спросят, куда ее поместить!
Ответ 3
Как сказал Кейт, это по дизайну. Этот учебник дает отличный пример, используя код, который я использовал для загрузки файла с сервера "правильным" способом. (Работает также в Silverlight 4)
Ответ 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