[WPF] WPF ProgressBar 컨트롤 MVVM 패턴으로 구현하기

소개

  • 안녕하세요. 오늘은 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

이 글을 공유하기

댓글

Designed by JB FACTORY