Новая тема открывает новое окно, как обновить текстовое поле в новом окне? - PullRequest
0 голосов
/ 08 ноября 2011

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

У меня есть следующий код для приложения WPF, вот код

Код из MainWindow.xaml.cs

public MainWindow()
{
  InitializeComponent();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
  Thread[] threads = new Thread[3];

  for (int i = 0; i < 3; i++)
  {
    int index = i;
    threads[i] = new Thread(new ThreadStart(test));
    threads[i].SetApartmentState(ApartmentState.STA);
    threads[i].IsBackground = true;
    threads[i].Start();
  }
}

public void test()
{
  OutputWindow outputwindow = new OutputWindow();
  outputwindow.Show();
  System.Windows.Threading.Dispatcher.Run();

  outputwindow.textBox1.Text = "writing";
  //some more stuff done
  //some more stuff done
  //some more stuff done
  outputwindow.textBox1.Text = "\nmore writing";
  //some more stuff done
  //some more stuff done
  //some more stuff done
  outputwindow.textBox1.Text = "\nmore writing";
}

Как я могу сделать так, чтобы textBox1.Text обновлялся при выполнении test ()?

С уважением!

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

Спасибоза ваши ответы, но я пока не смог заставить его работать.

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

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

public MainWindow()
{
  InitializeComponent();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
  Thread[] threads = new Thread[3];

  for (int i = 0; i < 3; i++)
  {
    int index = i;
    threads[i] = new Thread(new ThreadStart(test));
    threads[i].SetApartmentState(ApartmentState.STA);
    threads[i].IsBackground = true;
    threads[i].Start();
  }
}

public void test()
{
  OutputWindow outputwindow = new OutputWindow();
  outputwindow.Show();
  System.Windows.Threading.Dispatcher.Run();

  outputwindow.textBox1.Text = "writing";
  //some more stuff done
  //some more stuff done
  //some more stuff done
  outputwindow.textBox1.Text = "\nmore writing";
  //some more stuff done
  //some more stuff done
  //some more stuff done
  Action action = () => outputwindow.textBox1.Text = "\nmore writing";
  Dispatcher.Invoke(action);
}

Ответы [ 4 ]

1 голос
/ 08 ноября 2011

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

Проблема с вашим кодомНапример, вы вызываете Dispatcher.Run ().Проблема в том, что вы действительно должны вызвать Dispatcher.Run, чтобы сохранить окно с текстовым полем живым и отзывчивым, но внутри этого метода Dispatcher.Run есть бесконечный цикл.Вы застряли в строке кода Dispatcher.Run, пока Dispatcher не будет закрыт и окно не будет закрыто.Только тогда ваш код продолжит работу и выполнит эти выходные команды setWindow.textBox1.Text set, но теперь будет слишком поздно.Решением вашей проблемы является отделение outputWindow от вашего «рабочего кода».

Простейшей модификацией вашего кода будет помещение вашего «рабочего кода» в другой поток, чтобы вы не были заблокированы с помощью Dispatcher.Run().Вот как должен выглядеть ваш пример кода (поскольку вы предпочитаете создавать outputWindow в том же методе).

    // all good here
    public MainWindow()
    {
        InitializeComponent();
    }

    // also all good here
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Thread[] threads = new Thread[3];

        for (int i = 0; i < 3; i++)
        {
            int index = i;
            threads[i] = new Thread(new ThreadStart(test));
            threads[i].SetApartmentState(ApartmentState.STA);
            threads[i].IsBackground = true;
            threads[i].Start();
        }
    }

    // here's the change
    public void test()
    {
        OutputWindow outputwindow = new OutputWindow();
        outputwindow.Show();

        // here you create another thread which will execute your work code (the one you had after the Dispatcher.run statement
        Thread workThread = new Thread(new ParameterizedThreadStart(workMethod));
        workThread.IsBackground = true;
        // start the work thread BUT transfer the reference to outputwindow
        workThread.Start(outputwindow); 

        System.Windows.Threading.Dispatcher.Run();

        // no more code here; it has been transferd to workMethod which runs in another thread
    }

    public void workMethod(object threadParam)
    {
        OutputWindow outputwindow = (OutputWindow)threadParam;

        // those are little ugly but you must go through dispatcher because you are now in a different thread than your outputwindow
        outputwindow.Dispatcher.BeginInvoke((Action)(() => { outputwindow.textBox1.Text = "writing"; }), System.Windows.Threading.DispatcherPriority.Normal);
        //some more stuff done
        //some more stuff done
        //some more stuff done
        outputwindow.Dispatcher.BeginInvoke((Action)(() => { outputwindow.textBox1.Text = "\nmore writing"; }), System.Windows.Threading.DispatcherPriority.Normal);
        //some more stuff done
        //some more stuff done
        //some more stuff done
        outputwindow.Dispatcher.BeginInvoke((Action)(() => { outputwindow.textBox1.Text = "\nmore writing"; }), System.Windows.Threading.DispatcherPriority.Normal);

        // and finally close the outputWindow
        outputwindow.Dispatcher.InvokeShutdown();
    }
0 голосов
/ 08 ноября 2011

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

public static void DoEvents(this Application application)
{
    Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new VoidHandler(() => { }));
}

private delegate void VoidHandler();

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

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

Поскольку все остальные пишут здесь, вам нужно вызвать, если вы хотите изменить объекты UI. Но вы дали ему возможность использовать привязку данных вместо этого? Это отличный способ работать с WPF, вместо этого фактически связывая данные (в вашем случае это строка).

Здесь есть учебник: http://www.wpftutorial.net/DataBindingOverview.html

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

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

Он должен использовать invoke с disather для обновления элементов управления. Вы можете ссылаться на ссылки, как показано ниже.

http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher http://www.albahari.com/threading/part2.aspx#_Rich_Client_Applications

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...