代码之家  ›  专栏  ›  技术社区  ›  Willy

MVVM:在WPF NET 3.5中完成线程池工作项后更新视图的控件可见性

  •  1
  • Willy  · 技术社区  · 8 年前

    此启动绑定到视图模型中的属性“IsSplashVisible”,因此将属性更新为true,通知启动在开始时显示,并将其设置为false,通知启动隐藏。

    低于代码。

    :

    public class TestViewModel : BaseViewModel
    {
        private static Dispatcher _dispatcher;
        public ObservableCollection<UserData> lstUsers
    
        public ObservableCollection<UserData> LstUsers
        {
            get
            {
                return this.lstUsers;
            }
    
            private set
            {
                this.lstUsers= value;
                OnPropertyChanged("LstUsers");
            }
        }
    
        private bool isSplashVisible = false;
    
        public bool IsSplashVisible 
        {
                get
                {
                    return this.isSplashVisible;
                }
    
                set
                {
                    if (this.isSplashVisible== value)
                    {
                        return;
                    }
    
                    this.isSplashVisible= value;
                    OnPropertyChanged("IsSplashVisible");
                }
        }
    
        public TestViewModel()
        {
            this.IsSplashVisible = true;
    
            ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>
            {
                var result = getDataFromDatabase();
                UIThread(() => 
                {
                   LstUsers = result;
                   this.IsSplashVisible = false; <---- HERE IT FAILS
                });            
            }));
        }
    
        ObservableCollection<UserData> getDataFromDatabase()
        {            
            return this.RequestDataToDatabase();
        }
    
        static void UIThread(Action a)
        {
            if(_dispatcher == null) _dispatcher = Dispatcher.CurrentDispatcher;
            //this is to make sure that the event is raised on the correct Thread
            _dispatcher.Invoke(a); <---- HERE EXCEPTION IS THROWN
        }
    }
    
    1 回复  |  直到 8 年前
        1
  •  4
  •   Clemens    8 年前

    Dispatcher.CurrentDispatcher

    获取当前执行的线程的调度程序,如果尚未与该线程关联,则创建新的调度程序。

    您应该使用当前应用程序实例的调度程序:

    ThreadPool.QueueUserWorkItem(o =>
    {
        var result = getDataFromDatabase();
    
        Application.Current.Dispatcher.Invoke(() => 
        {
            LstUsers = result;
            IsSplashVisible = false;
        });            
    });
    

    Dispatcher.CurrentDispatcher 在UI线程中而不是在线程池线程中调用。然而,该字段是完全冗余的。你可以随时打电话 Application.Current.Dispatcher.Invoke()

    public class TestViewModel
    {
        private readonly Dispatcher _dispatcher = Dispatcher.CurrentDispatcher;
    
        public TestViewModel()
        {
            IsSplashVisible = true;
    
            ThreadPool.QueueUserWorkItem(o =>
            {
                var result = getDataFromDatabase();
    
                _dispatcher.Invoke(() => 
                {
                   LstUsers = result;
                   IsSplashVisible = false;
                });            
            });
        }
    
        ...
    }