问题
Here you have a simple WPF program:
<!-- Updater.xaml -->
<Window x:Class="Update.Updater"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<StackPanel>
<Button Click="Button_Click" Height="50"></Button>
<Label Content="{Binding Label1Text}" Height="50"></Label>
<Label Content="{Binding Label2Text}" Height="50"></Label>
</StackPanel>
</Grid>
</Window>
// Updater.xaml.cs
using System.Threading;
using System.Windows;
namespace Update
{
public partial class Updater : Window
{
public Updater()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Label1Text = "It is coming...";
Thread.Sleep(3000);
Label2Text = "It is here!";
}
public string Label1Text
{
get { return (string)GetValue(CategoryProperty); }
set { SetValue(CategoryProperty, value); }
}
static readonly DependencyProperty CategoryProperty = DependencyProperty.Register("Label1Text", typeof(string), typeof(Updater));
public string Label2Text
{
get { return (string)GetValue(Label2TextProperty); }
set { SetValue(Label2TextProperty, value); }
}
static readonly DependencyProperty Label2TextProperty = DependencyProperty.Register("Label2Text", typeof(string), typeof(Updater));
}
}
The intention is that when you click the button, the first label displays It is coming...
. Then the program sleeps for 3 seconds, and finally the second label displays It is here!
. However, the naïve implementation below doesn't work. If you run it and click the button the following happens: The program sleeps for 3 seconds, and then the two label texts are displayed simultaneously. Do you know how to correct the program so that it does as intended?
回答1:
Button_Click
is invoked by the UI thread, and you should not do anything requiring more than a few miliseconds in it, let alone sleeping for 3 seconds. Messages are not processed during that time, your interface is unresponsive, and your application is considered "hung" by the system.
So, that long processing task should be handled by another thread.
Something like that (untested):
private void Button_Click(object sender, RoutedEventArgs e)
{
Label1Text = "It is coming...";
var backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += (s,e) => {
Thread.Sleep(3000);
}
backgroundWorker.RunWorkerCompleted += (s,e) => {
Label2Text = "It is here!";
}
backgroundWorker.RunWorkerAsync();
}
Links:
BackgroundWorker
Build More Responsive Apps With The Dispatcher
回答2:
Try this:
label1.Content = "waiting...";
label1.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
{
label1.UpdateLayout();
}));
System.Threading.Thread.Sleep(3000);
label1.Content = "done!";
回答3:
You can use a storyboard and keyframe animation to do that.
http://msdn.microsoft.com/en-us/library/ms742868.aspx
There's a good example in here -
http://msdn.microsoft.com/en-us/library/system.windows.media.animation.stringanimationusingkeyframes.aspx
<Button Name="myAnimatedButton" Margin="200"
FontSize="16pt" FontFamily="Verdana">Some Text
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<StringAnimationUsingKeyFrames
Storyboard.TargetName="myAnimatedButton" Storyboard.TargetProperty="(Button.Content)"
Duration="0:0:8" FillBehavior="HoldEnd">
<!-- All the key frames below are DiscreteStringKeyFrames. Discrete key frames create
sudden "jumps" between values (no interpolation). Only discrete key frames can be used
for String key frame animations. -->
<DiscreteStringKeyFrame Value="" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="A" KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="An" KeyTime="0:0:1.5" />
<DiscreteStringKeyFrame Value="Ani" KeyTime="0:0:2" />
<DiscreteStringKeyFrame Value="Anim" KeyTime="0:0:2.5" />
<DiscreteStringKeyFrame Value="Anima" KeyTime="0:0:3" />
<DiscreteStringKeyFrame Value="Animat" KeyTime="0:0:3.5" />
<DiscreteStringKeyFrame Value="Animate" KeyTime="0:0:4" />
<DiscreteStringKeyFrame Value="Animated" KeyTime="0:0:4.5" />
<DiscreteStringKeyFrame Value="Animated " KeyTime="0:0:5" />
<DiscreteStringKeyFrame Value="Animated T" KeyTime="0:0:5.5" />
<DiscreteStringKeyFrame Value="Animated Te" KeyTime="0:0:6" />
<DiscreteStringKeyFrame Value="Animated Tex" KeyTime="0:0:6.5" />
<DiscreteStringKeyFrame Value="Animated Text" KeyTime="0:0:7" />
</StringAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
来源:https://stackoverflow.com/questions/10383116/implementing-a-pause-in-wpf