Любой способ обойти исключение "Диалоги должны быть инициированы пользователем"? - PullRequest
11 голосов
/ 04 ноября 2011

В моем приложении есть кнопка «Открыть файл».Перед запуском OpenFileDialog он спрашивает, хочет ли пользователь сохранить текущий файл, и если он это делает, он запускает SaveFileDialog.Затем он запускает OpenFileDialog.Довольно стандартные вещи.

Моя проблема в том, что silverlight тогда видит метод OpenFileDialog.ShowDialog () не инициированным пользователем, и я получаю исключение SecurityException.

Есть ли какой-либо известный разумный способ избежать этого исключения?Конечно, это довольно стандартный сценарий?

Приложение находится в браузере.

Любые идеи приветствуются

РЕДАКТИРОВАТЬ:

Извините, выпуск запрещенФактический код :( Однако логика довольно проста: в psuedocode событие нажатия кнопки «OpenFile» вызывает метод, подобный следующему:

* Запускает новое SL-сообщение с вопросом, сохранять ли сначала.

* В окне сообщения щелкнуло да / нет: -Если Нет, перейдите к Загрузить -Если Да, запустите SaveFileDialog.ShowDialog (), перейдите к Загрузить

* Загрузить: запустить диалог открытия файла

РЕДАКТИРОВАТЬ 2: Мини-программа ...

XML-контент для главной страницы:

<Grid x:Name="LayoutRoot" Background="White">
    <Button Content="Open" Click="Button_Click"/>
</Grid>

Код:

using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication15
{
public partial class MainPage : UserControl
{
    AskWindow aw = new AskWindow();

    public MainPage()
    {
        InitializeComponent();
        aw.Closed += new System.EventHandler(aw_Closed);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        aw.Show();
    }

    private void aw_Closed(object sender, System.EventArgs e)
    {
        if (aw.DialogResult == true)
        {
            SaveFileDialog svd = new SaveFileDialog();
            svd.ShowDialog();
        }


        OpenFileDialog ofd = new OpenFileDialog();
        ofd.ShowDialog();//Causes security exception
    }
}

public class AskWindow : ChildWindow
{
    public AskWindow()
    {
        Button b = new System.Windows.Controls.Button();
        b.Click += new System.Windows.RoutedEventHandler(b_Click);
        b.Content = "Yes, save it";
        this.Content = b;
    }

    private void b_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        this.DialogResult = true;
    }
}
}

Ответы [ 3 ]

4 голосов
/ 04 ноября 2011

Короткий ответ на ваш вопрос: "НЕТ" , потому что второй диалог больше не инициируется пользователем для времени выполнения Silverlight.То же самое верно, если вы отображаете MessageBox перед открытием диалога.

Вот некоторая информация из MSDN об ограничениях безопасности для диалогов

В целях безопасностиЕсли приложение Silverlight представляет собой изолированное приложение, диалоговые окна файлов и печати должны быть инициированы пользователем.Это означает, что вы должны показать их в результате действия, инициированного пользователем, такого как обработчик события click для кнопки.Если вы попытаетесь показать диалоговое окно из кода, не инициированного пользователем, возникнет исключение SecurityException.Кроме того, существует ограничение по времени, которое допускается между тем, когда пользователь запускает диалоговое окно, и когда оно отображается.Если временной интервал между этими действиями будет превышен, произойдет исключение.Когда вы используете отладчик Visual Studio с диалоговым окном, возникает исключение SecurityException, если вы устанавливаете точку останова между созданием диалогового окна и его отображением.Из-за ограничений, инициируемых пользователем, это ожидаемое поведение.Если вы установите точку останова после вызова ShowDialog, исключение не будет выдано.

Если вы попытаетесь отобразить диалоговое окно из обработчиков событий KeyDown и других синхронных вызовов кода приложения, таких как LayoutUpdated или обработчики событий SizeChanged, будет сгенерировано исключение.Однако исключение не будет выдано, когда приложение размещено в Internet Explorer и работает в защищенном режиме.

Плагин Silverlight имеет ограниченную поддержку диалоговых окон, когда плагин находится в полноэкранном режиме.,В большинстве случаев при отображении диалогового окна в полноэкранном режиме плагин возвращается во встроенный режим.Однако, чтобы избежать проблем в некоторых браузерах, вы должны выйти из полноэкранного режима перед использованием этих классов.В приложениях Silverlight, которые запускаются за пределами браузера, вы можете отобразить приглашение для пользователя включить диалоговые окна в полноэкранном режиме.Кроме того, ограничения для инициации пользователя ослаблены для доверенных приложений.Для получения дополнительной информации см. Доверенные приложения.

Ограничение по времени можно легко проверить с помощью следующего кода:

private void OpenDialog(object sender, RoutedEventArgs e) {
  MessageBox.Show("test");

  OpenFileDialog fileDialog = new OpenFileDialog();
  var result = fileDialog.ShowDialog();
}

Когда вы действительно быстро нажмете клавишу «Enter», когдаMessageBox отображается, OpenFileDialog отображается впоследствии, не вызывая никаких исключений безопасности.Но если вы оставляете MessageBox открытым на короткое время, после закрытия MessageBox возникает исключение SecurityException.

Я думаю, что ограничение по времени - это проблема отображения двух диалоговых окон один за другим, потому что ограничение по времени будет превышать показ первого.

3 голосов
/ 04 ноября 2011

Это может быть стандартный сценарий для настольного приложения , но вы не создаете настольное приложение.Вы создаете компонент, который запускается в защищенной изолированной программной среде и имеет некоторые довольно строгие ограничения по уважительным причинам.

Нет хитрого способа справиться с этим сценарием.Вы могли бы предоставить функцию закрытия «документа», которая будет отображать окно подтверждения, предупреждающее, что продолжающаяся воля теряет работу.

При попытке открыть другой «документ», пока текущий не сохранен, все, что вы можете сделать, это показать сообщение с инструкциейПользователь по своему выбору либо закроет текущий «документ» и откажется от его изменений, либо выберет сохранение.Пользователь должен будет выполнить эти действия вручную, а затем снова выбрать, чтобы открыть «документ».

Возможно, вы сможете немного улучшить ситуацию, если ваше приложение поддерживает несколько «открытых» документов, по крайней мере, пользователь не сможетне облагается налогом за открытие «документа».

0 голосов
/ 04 ноября 2011

Вы должны немедленно отобразить SaveFileDialog в обработчике мыши Click. В вашем случае это будет в private void b_Click.

Помещение препятствий между щелчком мыши и SaveFileDialog не будет работать.

...