我有一个标签我想在每秒后更新的内容,3秒后我只看到最后一个字符串“第3步......”我做错了什么,是否有另一种方法来实现这一目标由于某种原因,我无法使用Thread.Sleep():
查看:
<Window x:Class="WpfApplication1.ScrollerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Scroller" DataContext="{StaticResource scrollerVM}" Height="150" Width="300">
<Grid>
<ListBox ItemsSource="{Binding Messages}" Width="200" Height="50" BorderThickness="0" VerticalAlignment="Top" HorizontalAlignment="Left">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Text}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
<Button Width="70" Height="24" Content="Add new" Command="{Binding AddNew}" HorizontalAlignment="Left" Margin="0,56,0,30" />
</Grid>
</Window>
查看型号:
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
namespace WpfApplication1.Scroller
{
public class Message
{
public Message(string _text)
{
text = _text;
}
private string text;
public string Text
{
get { return text; }
set {text = value;}
}
}
public class ScrollerViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public DelegateCommand AddNew { get; protected set; }
ObservableCollection<Message> _messages = new ObservableCollection<Message>();
public ObservableCollection<Message> Messages
{
get { return _messages; }
set
{
_messages = value;
OnPropertyChanged("Messages");
}
}
public ScrollerViewModel()
{
AddNew = new DelegateCommand(Add);
}
private void Add(object parameter)
{
UpdateProgress("Step 1...");
UpdateProgress("Step 2...");
UpdateProgress("Step 3...");
}
private void UpdateProgress(string step)
{
Messages.Clear();
Messages.Add(new Message(step));
Thread.Sleep(1000);
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
答案 0 :(得分:5)
这是因为你正在UI线程中睡觉。在完成添加之前,UI将无法更新。您可以将BackgroundWorker与ReportProgress一起使用来实现您的目的。像这样:
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
worker.ReportProgress(1, "Step1");
Thread.Sleep(1000);
worker.ReportProgress(2, "Step2");
Thread.Sleep(1000);
worker.ReportProgress(3, "Step3");
};
worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
{
string step = (string)args.UserState;
Messages.Clear();
Messages.Add(new Message(step));
};
worker.RunWorkerAsync();
执行DoWork
时不会占用UI线程,但ProgressChanged
中的代码将在UI线程上执行。
答案 1 :(得分:2)
当你在UI线程上时,你永远不应该调用Thread.Sleep。这将阻止Dispatcher并且不进行渲染。在此期间将发生绑定更新等。
如果要在UpdateProgress()调用之间等待,请使用DispatcherTimer。
答案 2 :(得分:-1)
在添加新邮件之前,您正在清除邮件。
private void UpdateProgress(string step)
{
Messages.Clear(); // <- Why?
Messages.Add(new Message(step));
Thread.Sleep(1000);
}