How to run a progress bar in different thread in W

2019-02-21 00:36发布

问题:

I am populating the list view items dynamically. At the same time I wanna display a progress bar. When data populated the progress bar should be disabled. How to achieve this. I am new in WPF.

回答1:

You can use the BackgroundWorker class, which simplifies the handling of background threads when you are working with WPF. There are plenty of examples on the web for this. Here two from codeproject, but it's easy to find more examples:

http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo.aspx http://www.codeproject.com/KB/cpp/BackgroundWorker_Threads.aspx



回答2:

I prefer to control view state via presentation model. When view needs to populate items in address to presentation model that starts Worker thread and updates its progress values on UI synchronization context.

public class SampleModel : ObservableObject
{
    private ObservableCollection<string> _items = new ObservableCollection<string>();
    public IEnumerable<string> Items
    {
        get
        {
            return this._items;
        }
    }

    private int _progress;
    public int Progress
    {
        get
        {
            return this._progress;
        }
        set
        {
            if (this._progress != value)
            {
                this._progress = value;
                this.OnPropertyChanged("Progress");
            }
        }
    }

    public void Fill()
    {
        this.Progress = 0;
        var sc = SynchronizationContext.Current;

        new Thread(new ThreadStart(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    sc.Post(p =>
                        {
                            this._items.Add(i.ToString());
                            this.Progress ++;
                        }, null);
                    Thread.Sleep(100);
                }

                sc.Post(p =>
                {
                    this.Progress = 0;
                }, null);

            }))
            .Start();
    }
}

XAML:

<DockPanel>
    <ProgressBar Minimum="0"
                 Maximum="100"
                 Height="50"
                 Value="{Binding Progress}"
                 DockPanel.Dock="Top">
        <ProgressBar.Style>
            <Style TargetType="ProgressBar">
                <Setter Property="IsEnabled"
                        Value="True"/>
            </Style>
        </ProgressBar.Style>
    </ProgressBar>
    <Button Name="Start"
            DockPanel.Dock="Top">Start</Button>
    <ListView Name="List" 
              ItemsSource="{Binding Items}"/>
</DockPanel>

And code behind:

    public MainWindow()
    {
        InitializeComponent();
        this.Model = new SampleModel();
        this.Start.Click += new RoutedEventHandler(Start_Click);
    }

    void Start_Click(object sender, RoutedEventArgs e)
    {
        this.Model.Fill();
    }

    protected SampleModel Model
    {
        get
        {
            return (SampleModel)this.DataContext;   
        }
        set 
        {
            this.DataContext = value;
        }
    }