Создание MainWindow () и InitializeComponent () в WPF и C # - PullRequest
1 голос
/ 15 июля 2011

Этот код взят из моего приложения C # WPF:

public MainWindow()
{
    InitializeComponent();
    status("Getting dl links");
    getLinks();
}

Процедура getLinks в настоящее время отображает пару ссылок в окне сообщения.Эти ссылки отображаются в окне сообщения до того, как приложение WPF станет видимым.В этом случае это не проблема, но как мне показать прогресс (например, индикатор выполнения) любой процедуры, которую я хочу загрузить при запуске?

Ответы [ 2 ]

2 голосов
/ 15 июля 2011

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

public MainWindow()
{
    InitializeComponent();

    var progressBar = new ProgressBar();
    progressBar.Height = 40;
    progressBar.Width = 200;
    progressBar.Margin = new Thickness(100, 100, 100, 100);

    Task.Factory.StartNew(() =>
    {
        // getLinks();
        for (var i = 0; i < 5; i++)
        {
            Dispatcher.Invoke(new Action(() => { progressBar.Value += 20; }));

            Thread.Sleep(500);
        }
    });

    var stackPanel = new StackPanel();
    stackPanel.Children.Add(progressBar);

    Content = stackPanel;

}

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

Чтобы загрузить ссылки в другом потоке, я создаю новый Task, который является частью TPL ( Task Parallel Library ) в .NET 4.0. В этом случае я симулирую, что getLinks() требуется 5 * 500 миллисекунд для запуска, и что на самом деле это пять ссылок, которые будут загружены, следовательно, 20% за каждую итерацию.

Затем я добавляю 20 к значению progressBar, что указывает на то, что оно увеличилось на 20%.

Эта строка может немного смущать вас

Dispatcher.Invoke(new Action(() => { progressBar.Value += 20; }));

Но на самом деле это довольно распространено, когда вы выполняете многопоточное программирование с помощью GUI. Таким образом, проблема в том, что вы находитесь в другом потоке, мы запустили Task, который будет работать в отдельном потоке, и вы не можете обновить ваш поток пользовательского интерфейса из другого потока. Так что вам нужно что-то, что называется Dispatcher, и это доступно из вашего Window -класса.

Затем вы Invoke выполняете действие, а это значит, что вы просто говорите: «Запустите этот фрагмент кода для меня в этой теме».

И если вы хотите отобразить MessageBox, когда все загружено, вы можете просто добавить MessageBox.Show("Loaded!"); после for -loop.

1 голос
/ 15 июля 2011

Любые «загрузочные» задачи должны выполняться в фоновом потоке (см. Класс BackgroundWorker - в Google множество примеров). Таким образом, поток пользовательского интерфейса может свободно показывать ваше окно и обновлять его сообщениями о состоянии. В противном случае поток пользовательского интерфейса блокируется от каких-либо действий, пока загрузка не будет завершена.

...