[WPF] WPF ProgressBar 컨트롤 MVVM 패턴으로 구현하기
- C#/WPF
- 2021. 11. 27. 21:03
소개
- 안녕하세요. 오늘은 WPF에 대해서 학습해 보려고 합니다.
- 그 중에서도, ProgressBar 컨트롤을 MVVM 패턴으로 이용하여 구현하는 방법에 대해서 보여 드리려고 합니다.
- WPF에서 ProgressBar 컨트롤을 표현하기 위해서는 BackgroundWorker 쓰레드를 사용해서 표현해 주어야 합니다.
- 예제 코드를 통해서 바로 보여 드리도록 하겠습니다.
예제코드
MainWindow.xaml
<Window x:Class="WpfApp9.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:WpfApp9"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
</Window.Resources>
<Grid>
<StackPanel Orientation="Vertical">
<Button
Margin="30"
Width="70"
Command="{Binding StartWorkCommand}"
Content="Start" />
<!--PROGRESS BAR WITH TEXT-->
<Grid
Margin="20"
Visibility="{Binding ProgressVisibility, Converter={StaticResource booleanToVisibilityConverter}}">
<ProgressBar
Margin="20"
Height="20" Width="150"
Value="{Binding CurrentProgress, Mode=OneWay}" />
<TextBlock
Text="{Binding CurrentProgress, StringFormat={}{0:0}%}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace WpfApp9
{
/// <summary>
/// MainWindow.xaml에 대한 상호 작용 논리
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
}
MainWindowViewModel.cs
using System.ComponentModel;
using System.Threading;
using System.Windows.Input;
using WpfApp9.Base;
namespace WpfApp9
{
public class MainWindowViewModel : BindableBase
{
#region Properties
private string _title = "프로그레스바 MVVM 패턴";
public string Title
{
get { return _title; }
set { SetProperty(ref _title, value); }
}
private BackgroundWorker _worker;
private ICommand _startWorkCommand;
public ICommand StartWorkCommand
{
get
{
return _startWorkCommand
?? (_startWorkCommand = new DelegateCommand(_worker.RunWorkerAsync, !_worker.IsBusy));
}
}
private int _currentProgress;
public int CurrentProgress
{
get { return _currentProgress; }
private set { SetProperty(ref _currentProgress, value); }
}
private bool _progressVisibility;
public bool ProgressVisibility
{
get { return _progressVisibility; }
set { SetProperty(ref _progressVisibility, value); }
}
#endregion
public MainWindowViewModel()
{
InitProgressBar();
}
private void InitProgressBar()
{
_worker = new BackgroundWorker();
_worker.DoWork += DoWork;
_worker.WorkerReportsProgress = true;
_worker.ProgressChanged += ProgressChanged;
ProgressVisibility = false;
}
private void DoWork(object sender, DoWorkEventArgs e)
{
ProgressVisibility = true;
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(50);
(sender as BackgroundWorker).ReportProgress(i);
}
ProgressVisibility = false;
}
private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
CurrentProgress = e.ProgressPercentage;
if (CurrentProgress == 100)
ProgressVisibility = false;
}
}
}
BaseVM.cs
using System.ComponentModel;
namespace WpfApp9.Base
{
public class BaseVM : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
BindableBase.cs
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace WpfApp9.Base
{
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
DelegateCommand.cs
using System;
using System.Windows.Input;
namespace WpfApp9.Base
{
class DelegateCommand : ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new NullReferenceException("execute can not null");
_execute = execute;
_canExecute = canExecute;
}
public DelegateCommand(Action<object> execute, bool v) : this(execute, null) { }
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute.Invoke(parameter);
}
}
}
실행 결과
728x90
'C# > WPF' 카테고리의 다른 글
[WPF] WPF 점선 그리기 (0) | 2022.01.06 |
---|---|
[WPF 기본 문법] WPF TextBlock, Button 컨트롤 Style 사용하기 (0) | 2021.12.28 |
[WPF] WPF FolderBrowserDialog 네트워크 드라이브 보여주기 (0) | 2021.10.09 |
[WPF] WPF 관리자 권한으로 실행하기 (0) | 2021.09.28 |
[WPF 문법] WPF MVVM 패턴 이용하여 오라클 DB 연동하기 (2) | 2021.09.19 |
이 글을 공유하기