Как стать автором
Обновить

Комментарии 3

// ... 
    EnableWindow(handle, false);

    DispatcherFrame frame = new DispatcherFrame();

    this.Closed += delegate
    {
        EnableWindow(handle, true);
// ...


Плохой подход. Я не увидел (в C# не силен, может где-то неявно?), что фрейм дочерний по отношению к WindowInteropHelper(Application.Current.MainWindow). Это значит, что если вдруг этот маленький диалог попадет по Z-Order за MainWindow, то вернуть его оттуда будет сложно, т.к. MainWindow неактивно.
И второй момент с EnableWindow: нельзя так делать! Ниже правильный код:
BOOL fIsWindowEnabled = ! EnableWindow( handle, false );
// ...
EnableWindow( handle, fIsWindowEnabled );


Но это скорее к автору на CodeProject
Может я не понял цели данного проекта,
но ИМХО ваш код не работает:
Я просто создал на вашей форме еще одну кнопку и отодвинул диалог выровняв область его контента по верху окна.

Во время диалога — ничего не мешает пользоваться остальным UI (т.е. это уже не диалог)
В теории пользователь может обойти вашу капчу простым нажатием tab-tab — enter, пусть ему и не будут видны фокусы и сами элементы под диалогом, а есть еще Snoop который позволит снять IsEnabled с кнопки, который там не нужен:
— Кнопку блокируете через дополнительный IsEnabled="{Binding ButtonEnabled}",
хотя у вас же есть Command="{Binding ButtonClick}" (команда сама устанавливает видимость кнопки когда активна, а когда нет, если правильно установить область видимости команды, Snoop не поможет «взломщику», при таком сценарии т.к. даже если он снимет IsEnabled, команда всё равно будет не активной)

Т.е. по факту у вас обычный ContentPresenter поверх UI в который вы грузите UserControl.

Кажется, вы сделали не совсем то что задумывалось.


Вызов Dispatcher.PushFrame, конечно же, запускает новый цикл — вот только он запускается в текущем потоке. А вы только что перешли в пул потоков вызовом Task.Factory.StartNew! В итоге у вас работают два цикла сообщений, причём второй цикл работает полностью вхолостую, ведь к нему не привязано ни одного окна. И это вам ещё повезло что никаких проблем с многопоточностью не словили...


Вторая ошибка — вы каждый раз подписываетесь на ButtonClicked, а кто отписываться будет?


Правильнее для таких задач использовать асинхронность и TaskCompletionSource:


public async Task<string> GetInput()
{
    var tcs = new TaskCompletionSource<string>();

    Action handler = () => tcs.SetResult(Text);

    try 
    {
        ButtonClicked += handler;
        return await tcs.Task;
    }
    finally
    {
        ButtonClicked -= handler;
    }
}

public RelayCommand ButtonClick => new RelayCommand(async () => 
{
    await Task.Run(() => {
                // имитация работы
                Thread.Sleep(1000);
    });

    var control = new PopupControlModel();
    Result = await control.GetInput();

    await Task.Run(() => {
                // имитация дальнейшей работы
                Thread.Sleep(1000);
    });
});
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации