wpf обнаруживает открытое окно - PullRequest
2 голосов
/ 05 декабря 2009

В моем приложении WPF (csharp) у меня есть обработчик событий, который при запуске откроет новое окно (окно B) приложения и отобразит некоторые данные. Однако, когда событие запускается снова, если новое окно (окно B) все еще открыто, я не хочу порождать другой экземпляр окна B, а просто обновлять данные, отображаемые в текущем экземпляре. Таким образом, вопрос заключается в следующем: как определить, открыто ли окно B и открывается ли оно только в том случае, если его еще нет, в противном случае просто обновить данные?

Я нашел коллекцию Application.Current.Window, но почему-то у меня это пока не работает. Идеи?

Ответы [ 5 ]

5 голосов
/ 05 декабря 2009

Вы можете создать метод LoadWindow () в WindowB, который вы можете вызывать для загрузки (или обновления) данных и который будет работать независимо от того, открыто ли окно или нет. Попросите делегата позвонить, когда окно закроется:

private Action ParentCallbackOnClose;

public void LoadWindow( Action parentCallbackOnClose ) {
    // load the data (set the DataContext or whatever)

    ParentCallbackOnClose = parentCallbackOnClose;    

    // Open the window and activate/bring to the foreground
    Show( );
    Activate( ); 
}

и событие закрытия вашего окна вызывает делегата закрытия:

private void WindowClosed( object sender, EventArgs e ) {
     ParentCallbackOnClose.Invoke( );
}

Теперь из вашего класса, который открывает Window B, держите его за тот экземпляр, который он открывает, так что если WindowB уже открыт, когда кто-то пытается его перезагрузить, он просто вызывает LoadWindow для существующего экземпляра. Что-то вроде ...

private WindowB WinB;

private void LoadWindowB(Content content)
{
    if (WinB == null ){
        WinB = new WindowB( );
    }
    WinB.LoadWindow(content, WindowBClosed);
}

И тогда вы можете просто обнулить WinB при этом обратном вызове close, так что если WinB закрыт, то при следующем вызове LoadWindowB () он создаст новый экземпляр:

private void WindowBClosed( ){
    WinB = null;
}
0 голосов
/ 16 сентября 2013

Существует старый способ сделать это с помощью интерфейса. Я вижу это в Java как способ компенсировать отсутствие делегатов (поправьте меня, если я ошибаюсь). Этот метод позволит вам проверить, есть ли уже открытое окно (любого типа). Исходный ответ работает очень хорошо, но вы также можете сделать это следующим образом:

Создать интерфейс

public interface IWindowTracker
{
    void WindowIsOpened();
    void WindowIsClosed();
}

Реализация интерфейса на родительском (откуда вы открываете):

public partial class MainWindow : Window, IWindowTracker

В вашем конструкторе примите объект, который имеет интерфейс IwindowTracker. Сохраните экземпляр для будущего использования

    IWindowTracker windowTracker;
    public ProjectManager(IWindowTracker parentWindowTracker)
    {
        windowTracker = parentWindowTracker;

        InitializeComponent();
    }

Настройка вызовов для объекта окна отслеживания

    protected override void OnActivated(EventArgs e)
    {
        windowTracker.WindowIsOpened();
        base.OnActivated(e);
    }

    protected override void OnClosed(EventArgs e)
    {
        windowTracker.WindowIsClosed();
        base.OnClosed(e);
    }

и, наконец, реализовать IWindowTracker в родительском окне WPF

    bool windowIsOpen = false;

    public void WindowIsOpened()
    {
        windowIsOpen = true;
    }

    public void WindowIsClosed()
    {
        windowIsOpen = false;
    }

Это позволит вам следить за тем, открыто ли окно и если это так, нет необходимости открывать его новый экземпляр:

        if (!windowIsOpen)
        {
            remoteProjectManager = new ProjectManager(this);
            remoteProjectManager.Show();
        }

        remoteProjectManager.Focus();

Вызов show () для закрытого окна, похоже, вызывает исключение, поэтому я предполагаю, что есть какой-то другой способ или что, если вы закрыли окно, окно технически "уничтожено"

Приятно то, что я могу определить, все ли еще открыто окно, и сфокусироваться на нем (чтобы он снова выходил на передний план).

ПРИМЕЧАНИЕ: есть недостаток в том, что в этой настройке он ограничивает вас открытием только одного окна за раз (при условии, что все ваши окна реализованы таким образом). В моем случае я хочу открыть только одно окно, кроме основного.

Вы также можете проверить, является ли ваше окно пустым или нет, учитывая, что это, вероятно, не единственное окно, которое вам придется открывать.

0 голосов
/ 23 июня 2013

Так как это первая ссылка Google в списке, опубликованная несколько лет назад, для решения, чтобы проверить, открыт ли Window, я опубликую свой ответ для других, который, как мне кажется, проще реализовать. ChildWindow вызывается только с MainWindow, поэтому никаким другим Window проверять не нужно.

private void OpenChildWindow()
{
    if (this.OwnedWindows.OfType<ChildWindow>().Count() > 0)
    {
        ChildWindow Win = this.OwnedWindows.OfType<ChildWindow>().First();
        Win.Activate();
    }
    else
    {
        ChildWindow Win = new ChildWindow();
        Win.Owner = this;
        Win.Show();
    }
}
0 голосов
/ 09 февраля 2011

Эта статья это лучшее, что я нашел для передачи данных между страницами WPF. Автор использовал подход KISS для предоставления простого решения.

0 голосов
/ 05 декабря 2009

edit: Упс, мой ответ относится только к Windows Forms. я только что видел упоминание WPF. Я не уверен, каким будет конкретный код для WPF, но я думаю, что концептуально он не так уж и отличается. Я думаю, что в WPF свойство называется IsVisible вместо Visible

Вы можете удерживать экземпляр своего окна (или сделать его Singleton ), а затем, когда вам необходимо определить, является ли он видимым или нет, проверьте его свойство Visible.

например:

if(myWindow.Visible){
  myWindow.Hide();
}else{
  myWindow.Show();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...