2016-05-05 4 views
0

У меня есть прогресс бар, как это:Как сделать индикатор выполнения работы в MVVM?

<ProgressBar x:Name="import_bar" Minimum="0" Maximum="100" Orientation="Horizontal" Value="{Binding CurrentProgress, Mode=OneWay}" /> 

и ViewModel:

public class ViewImportProgressViewModel : BindableBase 
    { 
     MainTest mainTest; 

     public double CurrentProgress { get; set; } 

     public ViewImportProgressViewModel(MainTest mainTest) //constructor 
     { 
      this.mainTest = mainTest; 
      mainTest.ProgressUpdated += SetProgressBarValue; 
     } 

     private void SetProgressBarValue(double argument) 
     { 

      CurrentProgress = argument * 100; 
      OnPropertyChanged(() => CurrentProgress); 
     } 

    } 

и тестовый класс, который фактически устанавливает значение для прогресса:

public class MainTest 
    { 
     public delegate void ProgressUpdateHandler(double argument); 
     public event ProgressUpdateHandler ProgressUpdated; 

     public void RunTheLoop() 
     { 
      double progress=0; 

      for (int i = 1; i <= 30; i++) 
       { 
        //lenghty task code 

        ....... 


        //increment the progress bar 
        progress += 1/30; 


        if (i == 30) 
         progress = 1; 


        ProgressUpdated(progress); 

       } 

     } 

    } 

код работает ОК, и я вижу, что CurrentProgress получает правильное значение, но индикатор выполнения в пользовательском интерфейсе не обновляется. Может кто-нибудь, пожалуйста, помогите мне с этим?

Обновление;

Если я использовать не MVVM подход в код, как это:

public delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);    
UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(progress_bar.SetValue); 
Dispatcher.Invoke(updatePbDelegate, System.Windows.Threading.DispatcherPriority.Background, new object[] { System.Windows.Controls.ProgressBar.ValueProperty, CurrentProgress }); 

затем он работает.

+0

Что делает 'ProgressUpdated'? – Bijington

+0

Он отправляет «прогресс» в ViewModel, поэтому каждый раз, когда «прогресс» обновляется, «SetProgressBarValue()» вызывается в ViewModel и передает это значение в свойство «CurrentProgress» – Ivan

+0

Использует ли ваш класс 'ViewImportProgressViewModel'' INotifyPropertyChanged' ? – Bijington

ответ

1

Это довольно грубый подход, но он работает, используя MVVM подход

MainTest

public class MainTest 
{ 
    public delegate void ProgressUpdateHandler(double argument); 
    public event ProgressUpdateHandler ProgressUpdated; 

    public void RunTheLoop() 
    { 
     // This does not work 
     //this.PerformStuff(); 

     // This does 
     Task.Factory.StartNew(() => this.PerformStuff()); 
    } 

    private void PerformStuff() 
    { 
     double progress = 0; 

     for (int i = 1; i <= 30; i++) 
     { 
      Thread.Sleep(1000); 

      //increment the progress bar 
      progress += 1.0/30; 


      if (i == 30) 
       progress = 1; 


      ProgressUpdated(progress); 

     } 
    } 
} 

Посмотреть

public partial class MainWindow : Window 
{ 
    private MainTest test; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     this.test = new MainTest(); 
     this.DataContext = new ViewImportProgressViewModel(this.test); 

     this.Loaded += MainWindow_Loaded; 
    } 

    private void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     this.test.RunTheLoop(); 
    } 
} 

ViewModel

public class ViewImportProgressViewModel : INotifyPropertyChanged 
{ 
    MainTest mainTest; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public double CurrentProgress { get; set; } 

    public ViewImportProgressViewModel(MainTest mainTest) //constructor 
    { 
     this.mainTest = mainTest; 
     mainTest.ProgressUpdated += SetProgressBarValue; 
    } 

    private void SetProgressBarValue(double argument) 
    { 

     CurrentProgress = argument * 100; 

     this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurrentProgress")); 
    } 

} 
+0

Да, он получает правильное значение. – Ivan

+0

Я могу попробовать, но я почти уверен, что я выступаю в основном потоке, и я уже думал об этом как о проблеме. Я попытался переместить «RunTheLoop()» в отдельном потоке, но затем я получаю исключение ». Приложение называется интерфейсом, который был настроен для другого потока. (Исключение из HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)).' – Ivan

+0

Мой «длинный код задачи» состоит из вызовов методов, которые поступают из классов иерархических моделей, и исключение, о котором я упоминал, бросается в один из этих методов. – Ivan

Смежные вопросы