Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/37: Рейтинг темы: голосов - 37, средняя оценка - 4.68
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205

ProgressBar в MVVM

02.04.2022, 20:36. Показов 9547. Ответов 86
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Помогите, пожалуйста, нужно сделать индикатор выполнения (ProgressBar) какого-либо процесса в MVVM в Авалонии. Правильно, ли я делаю?

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:Test_progress.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="Test_progress.Views.MainWindow"
        Icon="/Assets/avalonia-logo.ico"
        Title="Test_progress">
 
    <Design.DataContext>
        <vm:MainWindowViewModel/>
    </Design.DataContext>
    <StackPanel>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
        </Grid>
        <ProgressBar Grid.Row="1" Height="20" Width="200" Name="progressBar" Margin="10" />
        <TextBlock Grid.Row="2" Name="MyTextBlock" HorizontalAlignment="Center" Margin="10"/>
        <Button Grid.Row="3" HorizontalAlignment="Center" Width="70" Content="Do_Work" Command="{Binding DoWork_button_click}" Margin="10" />
    </StackPanel>
</Window>

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
using Avalonia.Controls;
using Avalonia.Interactivity;
using System;
using System.ComponentModel;
using System.Threading;
 
namespace Test_progress.Views
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
           // progress = this.Find<ProgressBar>("progressBar");
        }
 
       private void DoWork_button_click(object sender, RoutedEventArgs e)
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
            worker.WorkerReportsProgress = true;
            worker.DoWork += Worker_DoWork;
            worker.ProgressChanged += Worker_ProgressChanged;
            worker.RunWorkerAsync();
 
        }
 
        private void Worker_ProgressChanged(object? sender, ProgressChangedEventArgs e)
        {
            progressBar.Value = e.ProgressPercentage;
            MyTextBlock.Text = (string)e.UserState;
        }
 
        private void Worker_DoWork(object? sender, DoWorkEventArgs e)
        {
            var worker = sender as BackgroundWorker;
            worker.ReportProgress(0, String.Format("Processing iteration 1"));
            for (int i=0; i<10; i++)
            {
                Thread.Sleep(1000);
                worker.ReportProgress((i+1)*10, String.Format("Processing iteration {0}", i+2));
            }
            worker.ReportProgress(100, "Done");
        }
 
        private void Worker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e)
        {
            progressBar.Value = 0;
            MyTextBlock.Text = " ";
        }
    }
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Avalonia.Controls;
using Avalonia.Interactivity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Threading;
 
namespace Test_progress.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
       
    }
}
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.04.2022, 20:36
Ответы с готовыми решениями:

ProgressBar в MVVM
Здравствуйте. Пытаюсь реализовать простой пример на MVVM. Суть работы заключается в работе функции в которой циклически ghjbc class...

Рисую линию без MVVM все ОК. C MVVM произвольный старт
Добрый день всем. Рисую линию при помощи анимации. Все получилось -рисуется, стирается. Но у нас все задания с MVVM, чтобы ViewModel...

Консольный progressbar или progressbar в TMemo
Здравствуйте. Хочу спросить ради интереса как создать вот такой ProgressBar но с указанием своих сиволов в консоли и в...

86
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
05.04.2022, 12:19
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Почему-то я думал, что с вами один раз что-то по Avalonia разбирали.
Ха-ха-ха, я и сам разбирался. Пришлось не одну статью перечитать. Просто самому было интересно.

Добавлено через 10 минут
Элд Хасп, вообще, где-где, а в Avalonia я бы рекомендовал использовать именно реактивное программирование.

Как бы сильно я не любил RelayCommand, но ReactiveCommand, всё таки, мне симпатизирует больше.

Он объективно превосходит все реализации комманд, которые я вообще видел.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
05.04.2022, 12:42
Цитата Сообщение от limeniye Посмотреть сообщение
Avalonia я бы рекомендовал использовать именно реактивное программирование.
Согласен.
Но вопрос в начале не затрагивал Avalonia и судя по нему ТС не потянет (с текущим уровнем) освоение реактивного программирования.
Я как понял, он и командах-то первый раз сейчас только услышал.
0
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
05.04.2022, 16:39  [ТС]
Цитата Сообщение от Sun1212 Посмотреть сообщение
индикатор выполнения (ProgressBar) какого-либо процесса в MVVM в Авалонии
вопрос был именно про Авалонию
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
05.04.2022, 16:47
Sun1212, я немного не в теме, но видел там ответы.

Вам нужно что-то объяснить, с чем-то помочь? Или тема закрыта? Соориентируйте, пожалуйста.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16166 / 11286 / 2892
Регистрация: 21.04.2018
Сообщений: 33,175
Записей в блоге: 2
05.04.2022, 18:24
Цитата Сообщение от Sun1212 Посмотреть сообщение
вопрос был именно про Авалонию
Ну, значит я тупанул - пока не показали не увидел этого.

Добавлено через 7 минут
Sun1212, у меня Avalonia даже не запустилась - когда-то пытался.
Поэтому могу ответить только по общим вопросам не специфичным для платформы.

Avalonia, по моему, неотделима от ReaciveUI.
Можно, конечно, его игнорировать и делать как на WPF, но, на мой взгляд, это бессмысленно.
Раз уж взялись за освоение Avalonia, то лучше изучить реактивное программирование.
1
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
05.04.2022, 19:15  [ТС]
Цитата Сообщение от limeniye Посмотреть сообщение
Вам нужно что-то объяснить, с чем-то помочь?
да, у меня изменилась задача...Нужно чтобы в одном проекте было реализовано окно с ProgressBar и TextBlock, а в другом проекте была кнопка "Do_work", по нажатию которой у нас появится окно с ProgressBar и TextBlock.

Я за основу взяла код из поста 6, прикрепляю свой проект.
Вложения
Тип файла: zip cyber_0504.zip (203.2 Кб, 2 просмотров)
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
05.04.2022, 19:27
Цитата Сообщение от Sun1212 Посмотреть сообщение
а в другом проекте была кнопка "Do_work"
Хм. Может Вы имел ввиду в другом окне?
0
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
05.04.2022, 19:31  [ТС]
limeniye, нет, надо именно в другом проекте. У меня в тесте в проекте Start кнопка, которая запустит проект Test_Progress.
За основу взяла код из поста 6, только кнопку перемещаю в другой проект
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
05.04.2022, 19:42
Цитата Сообщение от Sun1212 Посмотреть сообщение
У меня в тесте в проекте Start кнопка, которая запустит проект Test_Progress.
Что-то Вы путаете. Проект не запускается при нажатии на кнопку.
Проект запускается при запуске приложения.
Вы что-то путаете.

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

Писал "от руки" но +- вот так.
C#
1
2
3
4
5
6
7
8
private void OnStartClicked(object sender, RoutedEventArgs e)
{
    var progressBarWindow = new MyProgressBarWindow();
    progressBarWindow.Show();
 
    // или вот так ещё попробуйте
    // progressBarWindow.ShowDialog(Application.Current.MainWindow);
}
0
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
05.04.2022, 20:02  [ТС]
Цитата Сообщение от limeniye Посмотреть сообщение
Проект запускается при запуске приложения.
конечно, я это и имела ввиду. У меня в проекте окно ProgressBarView должно отобразиться при вызове из другой модели
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
06.04.2022, 01:05
Sun1212, понял, хорошо. В течении нескольких часов дам ответ.

Добавлено через 4 часа 53 минуты

Не по теме:

Sun1212, в течении нескольких часов не успеваю, есть там один ступор у меня. Буду разбираться уже после сна.

0
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
06.04.2022, 12:11  [ТС]
Цитата Сообщение от Sun1212 Посмотреть сообщение
Нужно чтобы в одном проекте было реализовано окно с ProgressBar и TextBlock, а в другом проекте была кнопка "Do_work", по нажатию которой у нас появится окно с ProgressBar и TextBlock
т.е. команда, привязанная к кнопке "DoWork" запустит асинхронную операцию (вызов окна с отображением ProgressBar). Заранее спасибо!
0
06.04.2022, 12:45

Не по теме:

Я уже разобрался с ошибкой. Чуток занят просто. Постараюсь, как буду свободен, дописать. Там буквально пару строк осталось.

0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
06.04.2022, 14:28
Часть Первая

View

По задаче у нас должно быть два проекта:

Проект А -- главный View-проект.
Проект B -- побочный.

В главном будет кнопка "Start", в побочном -- окно с ProgressBar'ом.

На "скорую руку" накидаю дизайн:
MainWindow
XML
1
2
3
4
5
6
7
8
9
10
11
12
<Window x:Class="A.MainWindow" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="A">
 
    <Button Background="#1e1e1e" Width="150" Height="60"
            HorizontalAlignment="Center" VerticalAlignment="Center"
            HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
        
        <TextBlock Text="Start" Foreground="White"/>
        
    </Button>
    
</Window>


ProgressWindow
XML
1
2
3
4
5
6
7
8
9
10
11
<Window x:Class="B.ProgressWindow" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="B">
 
    <Grid Background="#1e1e1e">
        <StackPanel VerticalAlignment="Center" Margin="50">
            <ProgressBar Value="20" Maximum="100"/>
            <TextBlock Text="20%" Foreground="White"/>
        </StackPanel>
    </Grid>
    
</Window>


Свойством Maximum мы задаём количество промежуточных делений.
Я указал 100, так как в процентном соотношении это проще считать.
Свойством Value, для теста, я указал "уже пройденный путь" (для теста).


Model
Супер! Теперь нам нужно чтобы была какая-то задача, которая выполнялась долго.
Я буду создавать 70 пустых файлов с промежутком 0.3 секунды.

Так как это уже какая-то "логика" программы, я создам для неё отдельный .Net 6 проект.


Назову его "Model", чтобы было понятно, что это слой Model паттерна Model <--> ViewModel <--> View.
Этот слой независим от Avalonia, там не должно быть реализаций INotifyPropertyChanged интерфейса.

В нём создам класс FileManagerService, он у нас будет отвечать за создание файлов.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    public class FileManagerService
    {
        public void CreateFiles(int count)
        {
            var catalogPath = @"C:\Files\";
 
            // Если каталога Files не существует на диске C
            if (!Directory.Exists(catalogPath))
            {
                // тогда мы его создаём
                Directory.CreateDirectory(Path.GetDirectoryName(@"C:\Files\"));
            }
 
            for (int i = 0; i < count; i++)
            {
                Thread.Sleep(300);
 
                // создаём пустой .txt файл
                File.Create(@"C:\Files\" + i + ".txt");
            }
        }
    }
То есть каждые 0.3 секунды создаётся файл на диске "C" в каталоге "Files".
Получается 70 файлов будут создаваться 2.1 секунду (300мс * 70файлов / 1000мс).
Супер, но теперь нам нужно оповещать программу каждый раз, когда мы создаём файл.

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

delegate -- это тематика оповещения. То есть то, о чём мы будем оповещать программу. Если взять пример с торговым центром, то это ТЕМА о закрытии какого-то отдела;
event -- это мы просто создаём таким образом сам "оповещатор", если его так можно назвать. Это наш микрофон, в который мы будем говорить;
.Invoke() -- тут мы оповещаем наши детские отделения о том, что торговый цент закрывается, а в скобочках мы указываем в котором часу именно он закрывается, например.


Теперь к практике:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    public delegate void FileCreatingProcessEventArgs(int fileIndex, int filesCount);
 
    public class FileManagerService
    {
        public event FileCreatingProcessEventArgs FileCreated;
 
        public void CreateFiles(int count)
        {
            var catalogPath = @"C:\Files\";
 
            // Если каталога Files не существует на диске C
            if (!Directory.Exists(catalogPath))
            {
                // тогда мы его создаём
                Directory.CreateDirectory(Path.GetDirectoryName(@"C:\Files\"));
            }
 
            for (int i = 0; i < count; i++)
            {
                Thread.Sleep(300);
 
                // создаём пустой .txt файл
                File.Create(@"C:\Files\" + i + ".txt");
 
                // "говорим в микрофон" что произошло создание файла
                FileCreated?.Invoke(i, count);
            }
        }
    }
Вернусь к примеру с созданием файлов.
FileCreatingProcessEventArgs -- это просто название события и его параметры.
В качестве параметров я указал:
fileIndex -- какой по счёту файл создался;
filesCount -- сколько всего файлов.

То есть каждый раз, когда будет создаваться файл, программа будет уведомлять нужные нам в ней места о том, что создался, например, 5ый файл из 70.

В дальнейшем я ещё раз пройдусь по объяснению этого сложного, для новичка, момента
И так, событие мы создали. Событие оповещает каждое создание файла. Но а кто "слушает" это событие? -- пока что никто.

Этим и будет заниматься наша ViewModel.

ViewModel

Слой ViewModel'и паттерна Model <--> ViewModel <--> View будет "слушать" что ей говорит Model и передавать эту информацию к View.

Выглядит это примерно так:
- создался файл;
- Model говорит "я создала файл 15ый из 70";
- ViewModel это услышала, обработала и оповестила об этом View;
- View узнала, что уже не 20% файлов создалось, а уже 21.4% -- и обновила информацию на ProgressBar'е.

Откуда взялись числа 20% и 21.4% -- это уже уровень ViewModel должен перевести 15 файлов из 70 в проценты.
То есть 100%/70*15 = 21.4%

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public class FileManagerViewModel
    {
        private readonly FileManagerService model = new FileManagerService();
 
        public FileManagerViewModel()
        {
            model.FileCreated += OnModelFileCreated;
        }
 
        private void OnModelFileCreated(int fileIndex, int filesCount)
        {
            double procent = (100/(double)filesCount) * (fileIndex + 1); // +1, потому что отсчёт начинается с нуля.
            Debug.WriteLine("Создано " + (fileIndex + 1) + "/" + filesCount + "\t -- " + procent + "%");
        }
    }
Тут я создаю объект model и подписываюсь на его событие FileCreated.
Вот этим вот += я и делаю эту самую "прослушку" события.
Теперь, когда в классе FileManagerService у нас срабатывает FileCreated?.Invoke(i, count);, то во ViewModel приходит эта информация (и для теста отображается в окне вывода).

View + ViewModel

Теперь нужно нажать на кнопку "Start" и запустить в model метод CreateFiles.
Чтобы не нарушать паттерн MVVM мы не будем задавать кнопке имя x:Name="button" или создавать обработчик нажатия по типу Button_Clicked.

Для этого используют привязки команды.

В классе FileManagerViewModel создаю команду, которая запускает метод CreateFiles в моделе.
C#
1
2
3
4
5
6
        public ReactiveCommand<Unit, Unit> CreateFilesCommand => ReactiveCommand.Create(CreateFilesExecute);
 
        private void CreateFilesExecute()
        {
            model.CreateFiles(70);
        }
Можно упростить эту запись до одной строки:
C#
1
        public ReactiveCommand<Unit, Unit> CreateFilesCommand => ReactiveCommand.Create(() => model.CreateFiles(70));
Теперь подвязываю Команду к нажатию на кнопку "Start"
XML
1
2
3
4
5
6
7
8
    <Button Background="#1e1e1e" Width="150" Height="60"
            Command="{Binding CreateFilesCommand}"
            HorizontalAlignment="Center" VerticalAlignment="Center"
            HorizontalContentAlignment="Center" VerticalContentAlignment="Center">
        
        <TextBlock Text="Start" Foreground="White"/>
        
    </Button>
На этом моменте у меня возникла ошибка.

Оказывается, просто так использовать Реактивное программирование, вместе с Avalonia, нельзя. Его нужно ещё подключить.

Для начала нужно установить два нугета для проекта A -- ReactiveUI и Avalonia.ReactiveUI


Потом переходит в файл Program.cs и в методе BuildAvaloniaApp
C#
1
2
3
4
        public static AppBuilder BuildAvaloniaApp()
            => AppBuilder.Configure<App>()
                .UsePlatformDetect()
                .LogToTrace();
нужно приконнектить наш ReactiveUI следующим образом:
C#
1
2
3
4
5
        public static AppBuilder BuildAvaloniaApp()
            => AppBuilder.Configure<App>()
                .UsePlatformDetect()
                .UseReactiveUI()
                .LogToTrace();
И теперь осталось подвязать саму ViewModel к View.
Я это сделаю самым простым способом: просто задам DataContext главному окну.
C#
1
2
3
4
5
6
7
8
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new FileManagerViewModel();
        }
    }
Итоги первой части

1. Мы нажали на кнопку, которая волняет команду в вью-моделе;
2. Команда запускает метод CreateFiles в моделе;
3. Метод, после каждого создания файла оповещает об этом (в этой строке - FileCreated?.Invoke(i, count););
4. Вью-модель "слушает" оповещения модели, благодаря "+=" ( в простонародье это называет подписка );
5. И когда приходит оповещение, запускается Debug.WriteLine("Создано " + ...);, которое выводит всё в окно вывода.

Выглядит это вот так:
2
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
06.04.2022, 15:13
Лучший ответ Сообщение было отмечено Sun1212 как решение

Решение

Часть вторая

Теперь у нас есть данные, осталось их просто выводить не в окно вывода, а в прогресс бар.

Для этого я немного изменю код.

Для удобства я модель сделаю статической:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    public static class FileManagerService
    {
        public static event FileCreatingProcessEventArgs FileCreated;
 
        public static void CreateFiles(int count)
        {
            var catalogPath = @"C:\Files\";
 
            // Если каталога Files не существует на диске C
            if (!Directory.Exists(catalogPath))
            {
                // тогда мы его создаём
                Directory.CreateDirectory(Path.GetDirectoryName(@"C:\Files\"));
            }
 
            for (int i = 0; i < count; i++)
            {
                Thread.Sleep(300);
 
                // создаём пустой .txt файл
                File.Create(@"C:\Files\" + i + ".txt");
 
                // "говорим в микрофон" что произошло создание файла
                FileCreated?.Invoke(i, count);
            }
        }
    }


Скопирую файл FileManagerViewModel в проект B.

Теперь в проекта А я этот файл я изменю и уберу оттуда всё лишнее, а также переименую его на MainWindowViewModel:
C#
1
2
3
4
    public class MainWindowViewModel
    {
        public ReactiveCommand<Unit, Unit> CreateFilesCommand => ReactiveCommand.Create(() => FileManagerService.CreateFiles(70));
    }
И изменю DataContext в MainWindow:
C#
1
2
3
4
5
6
7
8
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }
Таким образом я убрал всё лишнее из проекта A.

Так как модель теперь у нас статическая, то класс FileManagerViewModel, который теперь находится в проекте B, не нуждается в её инициализации и строки можно упростить.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
    public class FileManagerViewModel
    {
        public FileManagerViewModel()
        {
            FileManagerService.FileCreated += OnModelFileCreated;
        }
 
        private void OnModelFileCreated(int fileIndex, int filesCount)
        {
            double procent = (100/(double)filesCount) * (fileIndex + 1); // +1, потому что отсчёт начинается с нуля.
            Debug.WriteLine("Создано " + (fileIndex + 1) + "/" + filesCount + "\t -- " + procent + "%");
        }
    }
Я убрал оттуда команду, так как в окне ProgressWindow нет никакх кнопок.

Нужно не забыть подвязать теперь эту ViewModel к DataContext'у ProgressWindow
C#
1
2
3
4
5
6
7
8
    public partial class ProgressWindow : Window
    {
        public ProgressWindow()
        {
            InitializeComponent();
            DataContext = new FileManagerViewModel();
        }
    }
Теперь я изменяю команду таким образом, чтобы процесс создания файлов запустился асинхронно, а вместе с ним открылось окно:
C#
1
2
3
4
5
6
7
8
9
10
11
12
    public class MainWindowViewModel
    {
        public ReactiveCommand<Unit, Unit> CreateFilesCommand => ReactiveCommand.Create(CreateFilesExecute);
 
        private void CreateFilesExecute()
        {
            ProgressWindow newWindow = new ProgressWindow();
            newWindow.Show();
 
            Task.Run(() => FileManagerService.CreateFiles(70)); // Асинхронный запуск процесса создания файлов
        }
    }
Добавлено через 14 минут
Часть третья

Осталось лишь подвязать сам ProcessWindow к каким-то значениям
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    public class FileManagerViewModel : ReactiveObject
    {
        private int _progress;
        public int Progress { get => _progress; set => this.RaiseAndSetIfChanged(ref _progress, value); }
 
        public FileManagerViewModel()
        {
            FileManagerService.FileCreated += OnModelFileCreated;
        }
 
        private void OnModelFileCreated(int fileIndex, int filesCount)
        {
            Progress = (int)((100 / (double)filesCount) * (fileIndex + 1)); // +1, потому что отсчёт начинается с нуля.
        }
    }
XML
1
2
3
4
5
6
7
8
9
10
11
<Window x:Class="B.ProgressWindow" xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="B" Width="500" Height="200">
 
    <Grid Background="#1e1e1e">
        <StackPanel VerticalAlignment="Center" Margin="50">
            <ProgressBar Value="{Binding Progress}" Maximum="100"/>
            <TextBlock Text="{Binding Progress}" Foreground="White"/>
        </StackPanel>
    </Grid>
    
</Window>
2
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
06.04.2022, 15:30
Result
2
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
06.04.2022, 17:29  [ТС]
limeniye, спасибо огромное!!! Буду разбираться!

Добавлено через 2 минуты
limeniye, Благодарю за подробное объяснение!!!
0
06.04.2022, 17:30

Не по теме:

Sun1212, любые вопросы — не стесняйтесь. При возможности постараюсь ответить.

0
0 / 0 / 0
Регистрация: 12.12.2021
Сообщений: 205
06.04.2022, 19:16  [ТС]
limeniye, Подскажите, пожалуйста, в проекте В в ProgressWindow можно записать так:

XML
1
x:Class="B.Views.ProgressWindow"
?

у вас в коде
XML
1
x:Class="B.ProgressWindow"
Добавлено через 1 минуту
У меня пока ProgressBar не отображается при нажатии на кнопку...
0
 Аватар для limeniye
1182 / 624 / 160
Регистрация: 19.04.2018
Сообщений: 2,923
06.04.2022, 19:25
Sun1212, Вы можете изменить, но в таком случае Вам нужно будет изменить namespace в ProgressWindow.xaml.cs файле.

У меня там
C#
1
2
3
namespace B
{
}
Нужно изменить на
C#
1
2
3
namespace B.Views
{
}
Добавлено через 1 минуту
Sun1212, не отображается ProgessBar, или не отображается окно?

Добавлено через 3 минуты
У меня пока ProgressBar не отображается при нажатии на кнопку...
Sun1212 на форуме Обратить внимание администрации на это сообщение 0 Добавить +1 к оценке сообщения и его автора
А Вы задали DataContext?
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.04.2022, 19:25

Mvvm
Форумчане помогите разобраться есть простенькая модель public partial class Category:ViewModelBase { private int...

MVVM
Объясните пожалуйста следующие строки 1)Представление является подписчиком на событие изменения значений свойств или команд,...

MVVM
Здравствуйте, я в среде WPF нахожусь очень мало, посмотрел книжки, решил читать Мэтью Макдональда, стоит ли мне сразу изучать MVVM или...

x:Name в MVVM
Добрый день, как обращаться к объектам из VM по их x:Name? Например, у меня есть канвас в который я докидываю картинки по нажатию...

MVVM
Добрый день! Пытаюсь написать программу в стиле MVVM. Вопрос такой: как передать SelectedItem TreeView из xaml с помощью Binding в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru