【问题标题】:Implementing a pause in WPF在 WPF 中实现暂停
【发布时间】:2012-04-30 11:42:17
【问题描述】:

这里有一个简单的 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 秒,然后同时显示两个标签文本。您知道如何更正程序以使其按预期运行吗?

【问题讨论】:

    标签: c# wpf dependency-properties delay


    【解决方案1】:

    Button_Click 由 UI 线程调用,您不应在其中执行任何需要超过几毫秒的操作,更不用说休眠 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

    【讨论】:

      【解决方案2】:

      试试这个:

      label1.Content = "waiting...";
      
      label1.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate()
         {
      
              label1.UpdateLayout();
          }));
      
      System.Threading.Thread.Sleep(3000);
      label1.Content = "done!";
      

      【讨论】:

      • 这个建议和不使用调度器直接调用label1.UpdateLayout();有什么区别吗?
      • 是的,只是调用 UpdateLayout 是行不通的。该方法立即返回并安排更新以供稍后在 UI 线程中使用(可能在 Button Click 事件完成时)。然后线程休眠 3 秒,并安排另一次更改,当 Button Click 方法完成时,UI 线程最终渲染视图。在 Windows 窗体中,您可以只对 Label 使用 Update 方法,但 WPF 的工作方式不同。
      【解决方案3】:

      您可以使用故事板和关键帧动画来做到这一点。

      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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 2016-10-21
        • 1970-01-01
        • 1970-01-01
        • 2015-02-20
        相关资源
        最近更新 更多