2
votes

I have MainWindow which has its viewmodel MainWindowViewModel. Inside the window there is one textbox which accepts the user's input and a few radio buttons to filter the search and one button. The button action is bound to the viewmodel using a command like:

<Button x:Name="btnSearch" Command="{Binding SearchByCommand, Mode=OneWay}" />

Inside ViewModel there is:

public ICommand SearchByCommand
{
    get
    {
        if (_SearchByCommand == null)
        {
            _SearchByCommand = new RelayCommand(
                x => this.LoadData(this.SearchBy),
                x => { return !string.IsNullOrEmpty(this.SearchText); }
            );
        }
        return _SearchByCommand;
    }
}

And LoadData:

private void LoadData(string searchBy)
{
   switch(searchBy)
   ...
}

This works perfectly, but I don't know how to implement a progressbar in this solution. When the user clicks on the search button, the progressbar should start the progress and freeze the current UI. After loading data in the LoadData method the progressbar's progresscount should end and enable the UI again.

1

1 Answers

4
votes

You can use the busy indicator from the extended WPF toolkit: here.

Then you need to do your processing (LoadData) in another thread in order to not freeze the UI. To do so, the simple way is to use a background worker:

Add a boolean to your wm to indicate when the application is busy:

private bool isBusy;
public bool IsBusy
{
    get { return isBusy; }
    set
    {
        this.isBusy = value;
        this.OnPropertyChanged("IsBusy");
    }
}

Set up the background worker:

private void LoadData(string searchBy)
{
    IsBusy = true;
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += (o, ea) =>
    {
        //Do your heavy work here
    };

    worker.RunWorkerCompleted += (o, ea) =>
    {
        IsBusy = false;
    };

    worker.RunWorkerAsync();
}

If you want to show a progress bar with your current processing progress, you need to do a bit more work. First you need to apply a custom style to the busy indicator:

<toolkit:BusyIndicator IsBusy="True" BusyContent="Processing..." >
    <extToolkit:BusyIndicator.ProgressBarStyle>
        <Style TargetType="ProgressBar">
            <Setter Property="IsIndeterminate" Value="False"/>
            <Setter Property="Height" Value="15"/>
            <Setter Property="Margin" Value="8,0,8,8"/>
            <Setter Property="Value" Value="{Binding ProgressValue}"/>
        </Style>
    </extToolkit:BusyIndicator.ProgressBarStyle>
</toolkit:BusyIndicator>

Then add a ProgressValue property to your vm:

private int progressValue ;
public int ProgressValue
{
    get { return progressValue ; }
    set
    {
        this.progressValue = value;
        this.OnPropertyChanged("ProgressValue ");
    }
}

And report progress from the background worker:

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += (o, ea) =>
    {
        //Do your heavy work here
        worker.ReportProgress(10);

        //Do your heavy work here
        worker.ReportProgress(20);

        //And so on
    };

worker.ProgressChanged += (o,ea) =>
    {
        ProgressValue = e.ProgressPercentage;
    };

worker.RunWorkerCompleted += (o, ea) =>
    {
      IsBusy = false;
    };