【问题标题】:Update textbox in realtime in wpf giving no error with no output在 wpf 中实时更新文本框,没有错误,没有输出
【发布时间】:2017-11-03 09:03:30
【问题描述】:

我尝试了多种方法来尝试使其实时更新,因为我正在尝试制作一个简单的基于 GUI 的秒表。截至目前,我 NOT 试图让它看起来很漂亮,我只是想让程序运行。我已经包含了我尝试使用的方法来更新TextBlock。我尝试的最后一个是this.Dispatcher.Invoke( new Action(() => ... 方法。我尝试的另一种方法是使用我在 cmets 的代码中包含的 async-await 方法。

namespace WpfApp3
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
        private /*async*/ void start_Click(object sender, RoutedEventArgs e)
        {
            // await Task.Run(() =>
            {
                this.Dispatcher.Invoke( new Action(() =>
                {
                    Stopwatch Timer = new Stopwatch();
                    Timer.Start();
                    TimeSpan goneby = Timer.Elapsed;
                    string time = String.Format("{0:00}:{1:00}.{2:00}",
                            goneby.Minutes, goneby.Seconds,
                            goneby.Milliseconds / 10);
                    TextBlock textBlock = new TextBlock();
                    textBlock.Width = 100;
                    textBlock.Height = 50;
                    textBlock.HorizontalAlignment = HorizontalAlignment.Center;
                    textBlock.VerticalAlignment = VerticalAlignment.Top;
                    textBlock.Text = time;
                }));
                //  });
            }
        }
    }
}

这里是 XAML,以防万一需要解决这个问题:

<Window x:Name="window1" x:Class="WpfApp3.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="New Window" Height="300" Width="300">
    <Grid>
        <Button x:Name="start" Content="Start" HorizontalAlignment="Left" VerticalAlignment="Top" Width="213" Margin="38,181,0,0" Height="50" Click="start_Click"/>

    </Grid>
</Window>

【问题讨论】:

  • 你需要使用计时器而不是秒表
  • Invoke 在主 UI 线程上运行它,您需要使用 BeginInvoke()here is a link 来回答我对类似问题的回答。
  • 你定义了你的文本块,现在,只需将它添加到你的视觉元素之一。

标签: c# wpf xaml async-await dispatcher


【解决方案1】:

试试这个

<Window x:Class="WpfApp3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Name="lblTime"  FontSize="50" Margin="149,50,-149.333,-50.333" />

        <Button x:Name="start" Content="Start" HorizontalAlignment="Left" VerticalAlignment="Top" Width="213" Margin="149,166,0,0" Height="50" Click="start_Click"/>

    </Grid>

</Window>



using System;
using System.Timers;
using System.Windows;

namespace WpfApp3
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Timer timer;
        TimeSpan time;
        public MainWindow()
        {
            InitializeComponent();
            time = new TimeSpan(0);
            timer = new Timer();
            timer.Interval = 100;
            timer.Elapsed += timer_Elapsed;
        }

        private void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            time += new TimeSpan(0, 0, 0, 0, 100);
            this.Dispatcher.Invoke(() => {
                lblTime.Text = time.ToString(@"hh\:mm\:ss\:ff");
            });

        }

        private void start_Click(object sender, RoutedEventArgs e)
        {
            if (!timer.Enabled)
            {
                timer.Start();
                start.Content = "Stop"; 
            }
            else
            {
                timer.Stop();
                start.Content = "Start";
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    使用 async/await 是一个很好的解决方案。请注意,没有同步问题或需要锁定,因为所有代码都在 WPF 线程上运行。

    using System;
    using System.Timers;
    using System.Windows;
    
    namespace WpfApp3
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            bool running = false; // not running
            TimeSpan updateTime = TimeSpan.FromSeconds(0.1); 
            public MainWindow()
            {
                InitializeComponent();
            }
    
            // Note that async void should only be used for event handlers
            private async void start_Click(object sender, RoutedEventArgs e)
            {
                if (!running)
                {
                    start.Content = "Stop";
    
                    var watch = StopWatch.StartNew();
                    while(running){
                        var timeSpan = watch.Elapsed;
                        var message = 
                            $"Time: {timeSpan.Hours}h {timeSpan.Minutes}m " +
                                "{timeSpan.Seconds}s {timeSpan.Milliseconds}ms";
                        lblTime.Text = message
    
                        // async sleep for a bit before updating the text again
                        await Task.Delay(updateTime);
                    }
                }
                else
                {
                    running = false;
                    start.Content = "Start";
                }
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我的简单秒表版本:

      MainWindow.xaml

          <Window x:Class="Test.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:local="clr-namespace:Test"
              mc:Ignorable="d"
              Title="MainWindow" Height="350" Width="525">
          <Window.Resources>
              <local:StopwatchManager x:Key="stopwatchManager" />
          </Window.Resources>
          <Grid>
              <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding Source={StaticResource stopwatchManager}, Path=Stopwatch1.Duration, Mode=OneWay}" VerticalAlignment="Top" Height="27" Width="188"/>
              <Button x:Name="btnStart" Content="Start" HorizontalAlignment="Left" Margin="10,42,0,0" VerticalAlignment="Top" Width="53" Click="btnStart_Click"/>
              <Button x:Name="btnStop" Content="Stop" HorizontalAlignment="Left" Margin="68,42,0,0" VerticalAlignment="Top" Width="53" Click="btnStop_Click"/>
          </Grid>
      </Window>
      

      MainWinwdow.xaml.cs

      using System;
      using System.ComponentModel;
      using System.Timers;
      using System.Windows;
      
      namespace Test
      {
          public partial class MainWindow : Window
          {
              StopwatchManager stopwatchManager = new StopwatchManager();
              public MainWindow()
              { InitializeComponent(); }
      
              private void btnStart_Click(object sender, RoutedEventArgs e)
              { stopwatchManager.Stopwatch1.Start(); }
      
              private void btnStop_Click(object sender, RoutedEventArgs e)
              { /*SaveDuration();*/ stopwatchManager.Stopwatch1.Stop();  }
          }
      
          public class StopwatchManager
          {
              public Stopwatch Stopwatch1 { get { return _stopwatch1; } set { _stopwatch1 = value; } }
              static Stopwatch _stopwatch1 = new Stopwatch();
          }
      
          public class Stopwatch : INotifyPropertyChanged
          {
              private Timer timer = new Timer(100);
      
              public event PropertyChangedEventHandler PropertyChanged;
      
              public DateTime StartTime { get; set; } = DateTime.Now;
      
              public double Interval
              {
                  get { return timer.Interval; }
                  set { timer.Interval = value; }
              }
      
              public TimeSpan Duration { get { return DateTime.Now - StartTime; } }
      
              public Stopwatch()
              { timer.Elapsed += timer_Elapsed; }
      
              public void Start()
              { StartTime = DateTime.Now; timer.Start(); }
      
              public void Stop()
              { /*SaveDuration();*/ timer.Stop(); }
      
              private void timer_Elapsed(object sender, ElapsedEventArgs e)
              { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Duration")); }
          }
      }
      

      待办事项:

      -更改命名空间(“测试”)

      -实现“SaveDuration()”

      -Set UI-Updatetime => new Timer(100); //=0.1 秒

      -让多个秒表重复或使其成为列表

      public Stopwatch Stopwatch1 { get { return _stopwatch1; } set { _stopwatch1 = value; } }
      static Stopwatch _stopwatch1 = new Stopwatch();
      

      Source on GIT-Hub

      【讨论】:

        【解决方案4】:

        您需要创建计时器来更新您的文本块: 试试这个:

        public partial class Window1: Window   
        {  
            DispatcherTimer dt = new DispatcherTimer();  
            Stopwatch sw = new Stopwatch();  
            string currentTime = string.Empty;  
            public MainWindow()   
            {  
                InitializeComponent();  
                dt.Tick += new EventHandler(dt_Tick);  
                dt.Interval = new TimeSpan(0, 0, 0, 0, 1);  
            }  
            void dt_Tick(object sender, EventArgs e)   
            {  
               if (sw.IsRunning)   
               {  
                   TimeSpan ts = sw.Elapsed;  
                   currentTime = String.Format("{0:00}:{1:00}:{2:00}",  
                   ts.Minutes, ts.Seconds, ts.Milliseconds / 10);                                
                   YourtextBlock.Text = currentTime;
                }  
            }  
        
            private void startbtn_Click(object sender, RoutedEventArgs e)  
            {  
                sw.Start();  
                dt.Start();  
            }  
         } 
        

        原始来源: Here

        【讨论】:

          猜你喜欢
          • 2021-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多