简体   繁体   中英

Separate View not updating from background worker Mvvm

I am having issues updating a separately opened window's progress bar from a background worker inside another class.

The program execution goes like this:

  1. MainWindow loads
  2. Click button to do some work and open a popup progress bar (newly opened window)
  3. Background worker does work and reports progress to popup progress bar
  4. Popup progress bar hopefully updates.

The progress bar Value is bound to a property, which in the step-through debugger, looks to be getting updated okay by the background worker. These changes just are not reflected on the popup progress bar view. However, the binding is not broken because if I manually try and set the property value for the progress bar it works fine.

Furthermore, when I put the progress bar inside the initially started MainWindow view it updates fine. Any suggestions??

Here is the some code:

MainWindowViewModel

public class MainWindowViewModel: BaseViewModel
{

    private void PerformSomeAction()
    {
        var popUpProgressBar = new PopUpProgressBarViewModel();
        popUpProgressBar.Show(popUpProgressBar);

        var worker = new BackgroundWorker { WorkerReportsProgress = true };

        worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
        {
            if (args.ProgressPercentage != popUpProgressBar.Progresser)
            {
                Progresser = args.ProgressPercentage;
                popUpProgressBar.Progresser = args.ProgressPercentage;
            }
        };

        worker.DoWork += delegate
        {


            for (int i = 0; i < 101; i++)
            {
                worker.ReportProgress(i);
                System.Threading.Thread.Sleep(10);
            }


            MessageBox.Show("Done");
        };

            worker.RunWorkerAsync();

    }


    private int _progresser;
    public int Progresser
    {
        get { return _progresser; }
        set
        {
            if (_progresser == value) return;
            _progresser = value;
            OnPropertyChanged("Progresser");
        }
    }

    private RelayCommand _startProcessing; //set private member
    public ICommand StartProcessing //public field used by xaml binding
    {
        get
        {
            return _startProcessing = MakeCommandSafely(_startProcessing, () => PerformSomeAction());
        }
    }
}

PopUpProgressBarViewModel

public class PopUpProgressBarViewModel : BaseViewModel
{
    private PopUpProgressBar _popUpProgressBar;

    public void Show(PopUpProgressBarViewModel context)
    {
        _popUpProgressBar = new PopUpProgressBar {DataContext = context};
        _popUpProgressBar.Show();
    }

    private int _progresser;
    public int Progresser
    {
        get { return _progresser; }
        set
        {
            if (_progresser == value) return;
            _progresser = value;
            OnPropertyChanged("Progresser");
        }
    }
}

For full solution file (so you can see whats happening), see here

You are creating two PopUpProgressBarViewModels. You've got one that's being created as a resource inside PopUpProgressBar.xaml, and the other one is being created in MainWindowViewModel (line 18).

Your XAML is bound to the one created inside PopUpProgressBar.xaml, while the one that you're updating is the one created in MainWindowViewModel.

If you can pare it down so only one is created, that should solve your problem.

As @Doug said, since you are already setting the DataContext:

 _popUpProgressBar = new PopUpProgressBar {DataContext = context};

You can change the PopUpProgressBar to

 <Window x:Class="OpeningWindow_With_ProgressBar.View.PopUpProgressBar"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModel="clr-namespace:OpeningWindow_With_ProgressBar.ViewModel" Title="PopUpProgressBar" Height="150" Width="300">

<Grid>

    <StackPanel>
        <Label FontWeight="Bold">Loading Something</Label>
        <ProgressBar Minimum="0" Maximum="100" Margin="0,10,0,0" Height="25px" Width="250px" Value="{Binding Path=Progresser, Mode=OneWay}"></ProgressBar>
        <TextBlock Margin="10,10,0,0" Text="Details of loading..."></TextBlock>
    </StackPanel>

</Grid>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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