感谢您的时间。我有一个WPF这样的问题...它更新UI,只有当方法(由按钮点击触发)到达结束时才更新它。但是,在我的真实应用程序中,我需要立即更新UI以查看信息。
我试着阅读教程和帖子,我准备放弃....我会很感激任何想法为什么会发生和做什么: - )。
<TextBox Text="{Binding FirstName}"/>
<Button Content="Run" Click="Button_Click" />
public partial class MainWindow
{
public Person Person = new Person();
public MainWindow()
{
InitializeComponent();
DataContext = Person;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Person.FirstName = "John";
Thread.Sleep(10000);
///// Only Here I can see the update.
}
}
DataContext是:
public class Person:INotifyPropertyChanged
{
private string _FirstName;
public string FirstName
{
get { return _FirstName; }
set
{
if (_FirstName == value)
return;
_FirstName = value;
OnPropertyChanged("FirstName");
}
}
....
标准OnProertyChanged实施。
答案 0 :(得分:2)
您永远不应使用Sleep
阻止UI线程。相反,您可能希望将该部分代码放在后台线程上。例如,使用Task.Factory.StartNew:
private void Button_Click(object sender, RoutedEventArgs e)
{
Person.FirstName = "John";
Task.Factory.StartNew( () => {
Thread.Sleep(10000);
// ...
});
}
请注意,您无法在该线程内进行任何其他UI更改。如果需要,请使用Dispatcher.BeginInvoke
将其发送回UI线程。
例如,根据评论:
Person.FirstName = "John";
Task.Factory.StartNew( () => {
foreach (string mlsNumber in ourMlses)
{
Listing listing = sourceSite.ParseByMls(mlsNumber);
if (listing != null)
{
var successDb = sourceSite.UpdateListing(listing);
if (!successDb)
{
throw new Exception("Db error");
}
Dispatcher.BeginInvoke( () => {
// UI update that listing have been added to the DB
});
}
}
} );
答案 1 :(得分:0)
我假设您在Button_Click
方法中运行了一个冗长的操作,并希望首先使用新的 FirstName 更新UI。尝试用Dispatcher.Invoke方法结束 FirstName 初始化:
private void Button_Click(object sender, RoutedEventArgs e)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal,
new Action(() => {
Person.FirstName = "John";
}));
// Run a lengthy operation here
}
它将以与退出Button_Click方法后相同的方式触发PropertyChanged事件的UI更新。
P.S。但是,你在这里看到的所有代码都是非常糟糕的做法,我会谋杀一个编写它的开发人员。但它可能适合某些学术目的。要做出正确的解决方案,最好使用Commands并在 ViewModel 中处理它,而不是点击处理程序。