gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 21:01:16 26 4
gpt4 key购买 nike

我有一个 NET 3.5 和 Visual Studio 2008 下的 WPF MVVM 应用程序。 View 中的一些控件绑定(bind)到 View 模型上的属性,因此当这些属性更改时,它将通过 INotifyPropertyChanged 的​​实现通知到 View 。

开始时,我在窗口中央出现了一些“正在加载...”的飞溅字样,并且在从数据库请求某些数据时它保持可见。从数据库请求数据后,我想隐藏此启动画面。

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

开始时将属性“IsSplashVisible”设置为 true 没有问题,一旦排队的工作项完成,将属性设置为 false 时就会出现问题。一旦将此属性设置为 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
}
}

最佳答案

Dispatcher.CurrentDispatcher不是UI线程的Dispatcher,因为它

Gets the Dispatcher for the thread currently executing and creates a new Dispatcher if one is not already associated with the thread.

您应该使用当前 Application 实例的 Dispatcher:

ThreadPool.QueueUserWorkItem(o =>
{
var result = getDataFromDatabase();

Application.Current.Dispatcher.Invoke(() =>
{
LstUsers = result;
IsSplashVisible = false;
});
});

假设您的 TestViewModel 构造函数在 UI 线程中被调用,您可以如下所示编写它,其中 Dispatcher.CurrentDispatcher 在 UI 线程而不是 ThreadPool 线程中被调用。但是,该字段完全是多余的。您可以随时调用 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;
});
});
}

...
}

关于c# - MVVM:在 WPF NET 3.5 中完成线程池工作项后更新 View 的控件可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45300061/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com