- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个 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/
我在一个 fragment 中创建了一个自定义 ListView ,并将它与另一个 Activity 连接起来,以便在单击时显示列表中每个项目的详细信息。该 Activity 正在加载并显示标题、描述
当我打开搜索到的项目时,它打开的是 ListView 的第一项而不是搜索到的项目。即使成功搜索并找到项目。 举个例子: 如果我搜索 Arrow,我可以获得 Arrow,但是当单击 Arrow 时,它会
我是一名优秀的程序员,十分优秀!