[WPF] Prism Как из ViewModel показать диалоговое окно?
От: Glas  
Дата: 09.06.11 11:29
Оценка:
Делаю так:

Dialog dialog = new Dialog(){Owner = System.Windows.Application.Current.MainWindow};
dialog.ShowDialog();


Получаю исключение:

The calling thread must be STA, because many UI components require this.
Re: [WPF] Prism Как из ViewModel показать диалоговое окно?
От: Fortnum  
Дата: 09.06.11 12:53
Оценка:
Здравствуйте, Glas, Вы писали:

G>Делаю так:

G>
G>Dialog dialog = new Dialog(){Owner = System.Windows.Application.Current.MainWindow};
G>dialog.ShowDialog();
G>

G>Получаю исключение:
G>The calling thread must be STA, because many UI components require this.

Вы new Dialog() не из UI-потока вызываете. Попробуйте сделать так:

Dispatcher.BeginInvoke((Action)(()=>
{
    Dialog dialog = new Dialog(){Owner = System.Windows.Application.Current.MainWindow};
    dialog.ShowDialog();
}));


А свойство Dispatcher объявите где-нибудь в классе ViewModel'и:

public class ViewModel
{
    public Dispatcher Dispatcher { get; set; }
}


И предварительно проинициализируйте у ViewModel'и свойство Dispatcher из UI-потока, например в конструкторе ViewModel'и:

public ViewModel()
{
    Dispatcher = Dispatcher.CurrentDispatcher;
}
Re[2]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Glas  
Дата: 09.06.11 13:09
Оценка:
Здравствуйте, Fortnum, Вы писали:

Пробовал через Dispatcher, Exception не выходит, но и окна тоже нет
Re[3]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Fortnum  
Дата: 09.06.11 13:44
Оценка:
Здравствуйте, Glas, Вы писали:

G>Пробовал через Dispatcher, Exception не выходит, но и окна тоже нет


Непонятно тогда в чем проблема. Попробуйте может быть Owner убрать, может быть со стилями/шаблонами проблема, окно их не находит. Вот набросал примерчик, посмотрите в чем у вас отличие. Проект скачать можно здесь.

<Window
    x:Class="ShowOwnedDialog.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:l="clr-namespace:ShowOwnedDialog"
    Title="MainWindow" SizeToContent="Height" Width="500">
    
    <Window.DataContext>
        <l:MainWindowViewModel/>
    </Window.DataContext>

    <StackPanel Orientation="Vertical">
        <Button Content="В UI-потоке" Command="{Binding UIThreadCommand}"/>
        <Button Command="{Binding WorkThreadErrCommand}">
            <StackPanel TextBlock.TextAlignment="Center">
                <TextBlock Text="В рабочем потоке"/>
                <TextBlock Text="(с ошибкой the calling thread must be STA)"/>
            </StackPanel>
        </Button>
        <Button Command="{Binding WorkThreadNoErrCommand}">
            <StackPanel TextBlock.TextAlignment="Center">
                <TextBlock Text="В рабочем потоке"/>
                <TextBlock Text="(без ошибки - через Dispatcher.BeginInvoke)"/>
            </StackPanel>
        </Button>
    </StackPanel>

</Window>


class MainWindowViewModel
{
    public MainWindowViewModel()
    {
        Dispatcher = Dispatcher.CurrentDispatcher;

        UIThreadCommand = new RelayCommand(p =>
        {
            ShowDialogInternal();
        });

        WorkThreadErrCommand = new RelayCommand(p =>
        {
            new Thread(() =>
            {
                ShowDialogInternal();
            }).Start();
        });

        WorkThreadNoErrCommand = new RelayCommand(p =>
        {
            new Thread(() =>
            {
                Dispatcher.BeginInvoke((Action)(() =>
                {
                    ShowDialogInternal();
                }));
            }).Start();
        });
    }

    void ShowDialogInternal()
    {
        var dialog = new Dialog() { Owner = System.Windows.Application.Current.MainWindow };
        dialog.ShowDialog();
    }

    public Dispatcher Dispatcher { get; set; }

    public RelayCommand UIThreadCommand { get; private set; }

    public RelayCommand WorkThreadErrCommand { get; private set; }

    public RelayCommand WorkThreadNoErrCommand { get; private set; }
}
Re[4]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Glas  
Дата: 09.06.11 14:01
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Непонятно тогда в чем проблема. Попробуйте может быть Owner убрать, может быть со стилями/шаблонами проблема, окно их не находит. Вот набросал примерчик, посмотрите в чем у вас отличие. Проект скачать можно здесь.


Отличие в том, что используется Prism.
Re[5]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Fortnum  
Дата: 09.06.11 14:12
Оценка:
Здравствуйте, Glas, Вы писали:

F>>Непонятно тогда в чем проблема. Попробуйте может быть Owner убрать, может быть со стилями/шаблонами проблема, окно их не находит. Вот набросал примерчик, посмотрите в чем у вас отличие. Проект скачать можно здесь.

G>Отличие в том, что используется Prism.

Вряд ли Prism к невидимому окну какое-то отношение имеет. Разве что [Dependency] в code-behind на атрибутах стоят, но это надо видеть, играют они какую-нибудь роль или нет. У этого Dialog есть модель вида? Попробуйте ее не присоединять, будет окно видно в этом случае? Я имею в виду, что может еще с биндингом каких-нибудь свойств быть нестыковочка, окно уезжает куда-нибудь например.
Re[6]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Glas  
Дата: 09.06.11 14:28
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Вряд ли Prism к невидимому окну какое-то отношение имеет. Разве что [Dependency] в code-behind на атрибутах стоят, но это надо видеть, играют они какую-нибудь роль или нет. У этого Dialog есть модель вида? Попробуйте ее не присоединять, будет окно видно в этом случае? Я имею в виду, что может еще с биндингом каких-нибудь свойств быть нестыковочка, окно уезжает куда-нибудь например.


Я же говорю после BeginInvoke даже конструктор не вызывается.
Re[7]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Fortnum  
Дата: 09.06.11 17:24
Оценка:
Здравствуйте, Glas, Вы писали:

G>Я же говорю после BeginInvoke даже конструктор не вызывается.


Блин, а сказали окна нет Я почему-то подумал, что окно создается, но не появляется — у меня были такие проблемы Если через BeginInvoke получаете тот же Exception про STA thread, значит Dispatcher = Dispatcher.CurrentDispatcher сохраняете не в UI-потоке, а в рабочем! 100%.
Re[8]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Glas  
Дата: 09.06.11 17:43
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, Glas, Вы писали:


G>>Я же говорю после BeginInvoke даже конструктор не вызывается.


F>Блин, а сказали окна нет Я почему-то подумал, что окно создается, но не появляется — у меня были такие проблемы Если через BeginInvoke получаете тот же Exception про STA thread, значит Dispatcher = Dispatcher.CurrentDispatcher сохраняете не в UI-потоке, а в рабочем! 100%.


Через BeginInvoke вообще ничего не происходит
Re[9]: [WPF] Prism Как из ViewModel показать диалоговое окно
От: Fortnum  
Дата: 09.06.11 18:37
Оценка:
Здравствуйте, Glas, Вы писали:

G>Через BeginInvoke вообще ничего не происходит


Ну тогда точно BeginInvoke не у того Dispatcher'а вызываете. Dispatcher.CurrentDispatcher возвращает не NULL в любом потоке — и в рабочем и в UI, т.е. NULL-exception не возникнет в любом случае. В рабочем потоке только очередь не прокачивается и ваш вызов никогда не будет обработан, что видимо и происходит. Проверьте отладчиком в Watch методом Dispatcher.CurrentDispatcher.GetHashCode() в двух местах: (1) в конструкторе вида и (2) в месте, где вы сохраняете Dispatcher = Dispatcher.CurrentDispatcher — уверен, что хэш-коды у них будут разные.
Re[10]: [WPF] Prism Как из ViewModel показать диалоговое окн
От: Glas  
Дата: 09.06.11 19:16
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, Glas, Вы писали:


G>>Через BeginInvoke вообще ничего не происходит


F>Ну тогда точно BeginInvoke не у того Dispatcher'а вызываете. Dispatcher.CurrentDispatcher возвращает не NULL в любом потоке — и в рабочем и в UI, т.е. NULL-exception не возникнет в любом случае. В рабочем потоке только очередь не прокачивается и ваш вызов никогда не будет обработан, что видимо и происходит. Проверьте отладчиком в Watch методом Dispatcher.CurrentDispatcher.GetHashCode() в двух местах: (1) в конструкторе вида и (2) в месте, где вы сохраняете Dispatcher = Dispatcher.CurrentDispatcher — уверен, что хэш-коды у них будут разные.


да! Спасибо за идею Передал Dispatcher из Shell в модули и окошко появилось.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.