c# - 在后台工作人员的 RunWorkerCompleted 事件期间,未更新绑定(bind)到 View 模型属性的标签内容

标签 c# wpf mvvm

我在 View 模型中使用后台工作人员查看了 UI 更新的几个线程,并根据需要进行了代码更改,不幸的是我无法让它工作。

我正在尝试更新绑定(bind)到在 View 模型中实现 INotifyPropertyChanged 的​​属性的标签内容。报告已创建,但更新的标签内容仅在从主 WindowViewModel 重新打开 MyWindow 时显示。

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();        

        Messenger.Default.Register<NotificationMessage>(this, 
            NotificationMessageReceived);

        Closing += (s, e) => ViewModelLocator.Cleanup();
    }

    private void NotificationMessageReceived(NotificationMessage msg)
    {      
        if (msg.Notification == "ShowMyWindow")
        {
            MyWindow ReportWind = new MyWindow();
            ReportWind.DataContext = msg.Sender;
            MyWindow.ShowDialog();
        }
    }
}

ViewModel.cs
public class MyViewModel
{      
    //Fields 
    public static string statusProp = string.Empty;
    BackgroundWorker _BWorker = new BackgroundWorker();

    //Properties

    public string LblStatusContent
    {
        get
        {
            return statusProp;
        }
        set
        {
            statusProp = value;
            // Call OnPropertyChanged whenever the property is updated
            OnPropertyChanged("LblStatusContent");
        }
    }

    public RelayCommand GoCmd { get; private set; }

    public MyViewModel(IDialogService dService)
    {
        _dialogService = dService;
        GoCmd = new RelayCommand(() => Go(_dialogService), () => true);
    }

    private void Go(IDialogService dService)
    {
        //dialogservice to show a savedialogbox
        //do something.

        //start my thread to save a pdf refort
        _BWorker = new BackgroundWorker()
            {
                WorkerReportsProgress = true,
                WorkerSupportsCancellation = true
            };


        _BWorker.DoWork += new DoWorkEventHandler(DoWork);
        _BWorker.ProgressChanged += new      
            ProgressChangedEventHandler(WorkerProgress);
        _BWorker.RunWorkerCompleted += new 
        RunWorkerCompletedEventHandler(WorkerCompleted);

        if (_BWorker.IsBusy !=true)
        { 
            _BWorker.RunWorkerAsync();                        
        }
    }

    private void WorkerProgress(object sender, ProgressChangedEventArgs e)
    {
        try
        {
            if (e.UserState != null && e.UserState.ToString() != "")
            {
                // LblStatusContent =   
                //((ReportWindow.ReportProgressArg)e.UserState).smsg;
                //BatchCompareProgressBar.Value = e.ProgressPercentage;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            ErrorLogger.Log(LogLevel.Error, ex.ToString());
        }
    }

    private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        try
        {
            if ((e.Cancelled == true))
            {
                this.LblStatusContent = "Cancelled";
            }
            else if (!(e.Error == null))
            {
                LblStatusContent = "Failed to create report";
                OnPropertyChanged(LblStatusContent);
                LblStatusVisibility = System.Windows.Visibility.Visible;
            }
            else
            {
                System.Windows.Application.Current.Dispatcher.Invoke(
                    DispatcherPriority.Normal,
                    (Action)delegate()
                        {
                            this.LblStatusContent = "Report created successfully";
                            OnPropertyChanged(LblStatusContent);
                            LblStatusVisibility = System.Windows.Visibility.Visible;
                        });
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            ErrorLogger.Log(LogLevel.Error, ex.ToString());
        }
    }

    private void DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
            StartReport();                
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            ErrorLogger.Log(LogLevel.Error, ex.ToString());
        }
        finally { }
    }
}

MyWindow.xaml
<Label Name="lblStatus" VerticalAlignment="Center" 
       Content="{Binding LblStatusContent}" 
       Visibility="{Binding LblStatusVisibility, Mode=TwoWay}" 
       Margin="0,80,12,203" Height="36" 
       HorizontalAlignment="Right" Width="450" />

最佳答案

也许这个小例子可以帮助你弄清楚?

<Window x:Class="WpfApplication1.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModel="clr-namespace:WpfApplication1.ViewModel"
        Title="MainWindow"
        Height="80"
        Width="140">

    <Window.DataContext>
      <viewModel:MainViewModel />
    </Window.DataContext>

    <Label Content="{Binding Property}" />
</Window>
namespace WpfApplication1.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        readonly BackgroundWorker _worker = new BackgroundWorker();
        private string _property;

        public MainViewModel()
        {
            _worker.WorkerReportsProgress = true;
            _worker.DoWork += (sender, args) =>
                {
                    int iterations = 0;
                    Property = "Starting...";
                    Thread.Sleep(1000); 

                    while (iterations < 5)
                    {
                        _worker.ReportProgress(iterations * 25);
                        iterations++;
                        Thread.Sleep(350);
                    }
                };

            _worker.ProgressChanged += (sender, args) => 
                Property = string.Format("Working...{0}%", args.ProgressPercentage);

            _worker.RunWorkerCompleted += (sender, args) => 
                {
                    Property = "Done!";
                };

            _worker.RunWorkerAsync();
        }

        public string Property
        {
            get { return _property; }
            set { _property = value; RaisePropertyChanged(); }
        }
    }
}

关于c# - 在后台工作人员的 RunWorkerCompleted 事件期间,未更新绑定(bind)到 View 模型属性的标签内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32383343/

相关文章:

c# - 查看/检索属性

c# - 在 WPF Slider 中,拇指没有立即用 wacom 板拖动

.net - 在.Net 3.0中使用MVVM设计模式

wpf - 在 MVVM 中,在 ViewModel 中 Hook 模型项的事件会导致内存泄漏吗?

c# - WPF:一排长度相等的 ToggleButtons?

c# - 在遍历集合时从 ObservableCollection 中删除项目

c# - tostring ("000.0") 生成错误值

c# - blittable 类型的多维数组 - 如何获得指向内存的固定不安全指针?

c# - 在 ListView 的 gridview 中使用空格/输入选中/取消选中复选框 - wpf

wpf - 使用多种类型的控件搜索并突出显示 WPF 窗口上的任何文本