2012-04-30 2 views
1

Здесь у вас есть простая программа WPF:Реализация паузы в WPF

<!-- 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)); 
    } 
} 

Намерение состоит в том, что при нажатии кнопки, первая метка отображается It is coming.... Затем программа спит в течение 3 секунд, и, наконец, вторая метка отображает It is here!. Однако наивная реализация ниже не работает. Если вы запустите его и щелкните по кнопке, произойдет следующее: программа засыпает в течение 3 секунд, а затем два текста ярлыков отображаются одновременно. Вы знаете, как исправить программу, чтобы она выполнялась по назначению?

ответ

10

Button_Click вызывается в потоке пользовательского интерфейса, и вы должны не сделайте что-нибудь, требующее больше нескольких миллисекунд, не говоря уже о спящем в течение 3 секунд. Сообщения не обрабатываются в течение этого времени, ваш интерфейс не отвечает, и ваше приложение считается «зависающим» системой.

Таким образом, эта задача длительной обработки должна обрабатываться другим потоком.

Нечто подобное (непроверенные):

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(); 
    } 

Ссылки:

BackgroundWorker

Build More Responsive Apps With The Dispatcher

0

Вы можете использовать анимацию раскадровки и анимацию ключевого кадра, чтобы сделать это.

http://msdn.microsoft.com/en-us/library/ms742868.aspx

Там хороший пример здесь -

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> 
5

Попробуйте это:

label1.Content = "waiting..."; 

label1.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate() 
    { 

     label1.UpdateLayout(); 
    })); 

System.Threading.Thread.Sleep(3000); 
label1.Content = "done!"; 
+0

Есть ли разница между этим предложением и просто вызвать 'label1.UpdateLayout(); 'без использования диспетчера? – user181813

+1

Да, это не работает, просто вызвав UpdateLayout. Метод возвращается немедленно и планирует обновление для последующего использования в потоке пользовательского интерфейса (возможно, когда событие Button Click завершается). Затем поток засыпает в течение 3 секунд и планирует другое изменение, и когда метод Button Click заканчивается, поток пользовательского интерфейса, наконец, отображает представление. В Windows Forms вы можете использовать только метод Update на ярлыке, но WPF работает по-разному. –

Смежные вопросы