2017-06-02 91 views
0

我嘗試了多種方法來試圖讓它實時更新,因爲我試圖製作一個簡單的基於GUI的秒錶。截至目前,我是不是試圖讓它看起來很漂亮,我只是想讓程序運行。我已經包含了我試圖用來更新TextBlock的方法。我嘗試的最後一個是this.Dispatcher.Invoke(new Action(() => ...方法。我嘗試的另一種方法是使用我在註釋中的代碼中包含的async-await方法。在wpf中實時更新文本框,給出沒有輸出的錯誤

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> 
+0

你需要使用計時器不秒錶 – Krishna

+0

'Invoke'運行它在主UI線程什麼你需要使用'BeginInvoke()'和[這裏是一個鏈接](https://stackoverflow.com/a/39926050/2029607)來解決類似問題。 – XAMlMAX

+0

現在,您定義了您的文本塊,只需將其添加到您的某個視覺元素上即可。 – GBursali

回答

0

您需要創建一個定時器來更新您的文本塊: 試試這個:

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

0

嘗試這

<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"; 
      } 
     } 
    } 
} 
0

使用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"; 
      } 
     } 
    } 
} 
0

我的一個簡單的秒錶的版本:

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

TODO:

- 更改名字空間( 「測試」)

- 實施 「SaveDuration()」

- 設置UI-更新時間=>新定時器(100); //=0.1秒

- 要獲得multible秒錶複製或使其列表

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

Source on GIT-Hub