Member 13050667 Ответов: 2

Как получить доступ - обновить новое окно (C#, WPF)


У меня есть окно а, где я обрабатываю больший XML-файл в цикле foreach.
Перед циклом я планирую создать новое окно "прогресс" (B), и внутри цикла я должен иметь возможность обновить окно B, как был обработан пакет XY.

Любая идея, ссылка, образец или более простой способ сделать это?

Спасибо за любую подсказку!

Что я уже пробовал:

Я попытался создать новый поток, а также вызвать текстовое поле в окне B, но безуспешно

2 Ответов

Рейтинг:
8

TheRealSteveJudge

Пожалуйста, взгляните на этот образец:

Файл MainWindow.язык XAML

<Window x:Class="WpfProgressTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfProgressTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="1" Height="30">
            <ProgressBar Name="ProgressBar"
                         Foreground="Blue"></ProgressBar>
            <TextBlock Name="TextBlockProgress"
                       FontFamily="Arial"
                       FontSize="16"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       Background="Blue" 
                       Foreground="White"></TextBlock>
        </Grid>
        <StackPanel Grid.Row="2">
            <Button Name="ButtonStart" Width="75" Height="25" Margin="5" Content="Start" Click="ButtonStart_OnClick"></Button>
        </StackPanel>
    </Grid>
</Window>

Файл MainWindow.язык XAML.в CS
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace WpfProgressTest
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonStart_OnClick(object sender, RoutedEventArgs e)
        {
            var itemsCount = 10;

            ProgressBar.Minimum = 0;
            ProgressBar.Maximum = itemsCount;

            var task = new Task(() =>
            {
                for (var i = 0; i < itemsCount; i++)
                {
                    // Just for simulation of some work
                    Thread.Sleep(500);

                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        ProgressBar.Value++;
                        TextBlockProgress.Text = $"[{ProgressBar.Value}/{ProgressBar.Maximum}]";
                    });
                }
            });

            task.Start();
        }
    }
}

Вы должны выполнять тяжелую работу по обработке XML в задаче или потоке.
Для имитации рабочей нагрузки я добавил Сон в 500 мс.
После каждой итерации вы должны обновлять индикатор выполнения и текст
пользуясь Приложение.Текущий.Диспетчер.Взывать.
Это необходимо, поскольку вы не можете получить доступ к компонентам пользовательского интерфейса из другого потока.


Рейтинг:
12

OriginalGriff

Лучший способ сделать это-наоборот.

Переместите весь "обрабатывающий" код в отдельный поток: Класс BackgroundWorker (System.ComponentModel) | Microsoft Docs[^] - это хороший выбор, потому что он обеспечивает отчетность о ходе работы без каких-либо проблем с кросс-потоковым пользовательским интерфейсом.

Затем используйте механизм отчетности для обновления формы выполнения (или даже просто контроля выполнения в вашей основной форме.

Ссылка содержит простой пример.


Maciej Los

5ed!