简体   繁体   English

进度条MVVM?

[英]Progress-bar MVVM?

I am having a little bit of trouble getting a ProgressBar to work. 使ProgressBar正常工作有点麻烦。 When I start it up, nothing happens and I can't see why? 当我启动它时,什么也没发生,我看不出为什么?

I thought that this would start the task worker.RunWorkerAsync(); 我以为这将启动任务worker.RunWorkerAsync();

The below example should be able to be copied and pasted into a new solution and be run for testing if needed. 下面的示例应该能够复制并粘贴到新的解决方案中,并在需要时运行以进行测试。

The XAML, XAML,

<Grid Margin="20">
    <ProgressBar 
        Height="60"
        Minimum="0" 
        Maximum="100"
        Value="{Binding Progress, Mode=OneWay}" 
        Visibility="{Binding ProgressVisibility}"/>
</Grid>

My code, 我的代码

public partial class MainWindow : Window
{
    public ProggressbarViewModel PsVm { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        PsVm = new ProggressbarViewModel();
    }

    public class ProggressbarViewModel
    {
        public ProggressbarViewModel()
        {
            var worker = new BackgroundWorker();
            worker.DoWork += DoWork;
            worker.ProgressChanged += ProgressChanged;
            worker.RunWorkerAsync();
        }

        private int _progress;

        public int Progress
        {
            get { return _progress; }
            set
            {
                if (_progress == value) return;
                _progress = value;
                OnPropertyChanged();
            }
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                Thread.Sleep(100);
                _progress = i;
                OnPropertyChanged();
            }
        }

        private void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Progress = e.ProgressPercentage;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Any help would be much appreciated. 任何帮助将非常感激。

EDIT: The question is is similar possibly a duplicate in that sense, however the linked answer did not solve my problem, like it states in the Duplicate banner. 编辑:从这个意义上讲,这个问题很可能是重复的,但是链接的答案并没有解决我的问题,就像在重复横幅中指出的那样。

When you're not explicitly indicating source object for your bindings (by means of Binding.Source or Binding.RelativeSource properties), the framework uses (possibly inherited) value of DataContext of the target object as the source. 当您没有为绑定明确指定源对象时(通过Binding.SourceBinding.RelativeSource属性),框架将使用(可能是继承的)目标对象的DataContext值作为源。 The problem is that you don't assign your view-model to the DataContext property of any control. 问题是您没有将视图模型分配给任何控件的DataContext属性。 Thus, the source for the bindings resolves to null and nothing is showing on your progress bar. 因此,绑定源解析为null并且进度条上没有任何显示。

To resolve your issue you should assign your view model to the DataContext of your MainWindow : 要解决您的问题,您应该将视图模型分配给MainWindowDataContext

public MainWindow()
{
    InitializeComponent();
    PsVm = new ProggressbarViewModel();
    DataContext = PsVm;
}

If however you're planning on using different DataContext for your window, you can bind DataContext of ProgressBar : 但是,如果您打算为窗口使用其他DataContext ,则可以绑定ProgressBar DataContext

<ProgressBar
    DataContext="{Binding Path=PsVm,
                          RelativeSource={RelativeSource AncestorType=local:MainWindow}}"
    (...) />

You could also modify particular bindings by prepending PsVm. 您还可以通过在前面添加PsVm.修改特定的绑定PsVm. to the value of Path and using RelativeSource , eg: Path的值并使用RelativeSource ,例如:

 Value="{Binding Path=PsVm.Progress,
                 RelativeSource={RelativeSource AncestorType=local:MainWindow},
                 Mode=OneWay}"

In that case however you'd have to modify each binding, so previous solutions are quicker and/or simpler. 但是,在那种情况下,您必须修改每个绑定,因此以前的解决方案更快和/或更简单。

As a side note, you might also want to change the way you're reporting progress - note that OnPropertyChanged in your DoWork method is not called from UI thread. 作为一个侧面说明,你可能也想改变你报告进度的方式-那笔记OnPropertyChanged在你DoWork方法从UI线程调用。 The proper way to do it would be: 正确的方法是:

private void DoWork(object sender, DoWorkEventArgs e)
{
    var worker = (BackgroundWorker)sender;
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(100);
        worker.ReportProgress(i); //This will raise BackgroundWorker.ProgressChanged
    }
}

Also, in order to support progress reporting, you should set WorkerReportsProgress to true on your worker, eg: 另外,为了支持进度报告,您应该在工作程序WorkerReportsProgress设置为true ,例如:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM