私はhh:mm:ssというテキストボックスに結果を表示するwpfカウントダウンタイマーを作成したいと思います。wpfカウントダウンタイマーを作成するには?
11
A
答えて
21
DispatcherTimer
クラス(msdn)を使用できます。
TimeSpan
の構造(msdn)で保持できる時間。
TimeSpan
〜hh:mm:ss
をフォーマットする場合は、 "c"引数(msdn)を使用してToString
メソッドを呼び出す必要があります。
例:
XAML:
<Window x:Class="CountdownTimer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Name="tbTime" />
</Grid>
</Window>
コードビハインド:
using System;
using System.Windows;
using System.Windows.Threading;
namespace CountdownTimer
{
public partial class MainWindow : Window
{
DispatcherTimer _timer;
TimeSpan _time;
public MainWindow()
{
InitializeComponent();
_time = TimeSpan.FromSeconds(10);
_timer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
{
tbTime.Text = _time.ToString("c");
if (_time == TimeSpan.Zero) _timer.Stop();
_time = _time.Add(TimeSpan.FromSeconds(-1));
}, Application.Current.Dispatcher);
_timer.Start();
}
}
}
3
この目的のためにDispatcherTimer
を使うことには何も問題はありません。しかし、IMHOの最新のTPLベースのasync
/await
パラダイムは、読み書きが容易なコードを作成します。また、コードビハインドから直接UI要素の値を設定するのではなく、WPFプログラムに常に良いMVVMの方法を使用する方が良いです。
質問に記載されているようなカウントダウンタイマーを実装していますが、これらのより現代的なプラクティス&hellipを使用したプログラムの例です。
興味深いコードの大部分が存在する場所ビューモデルはもちろんであり、さらにはそこに主なものは、実際のカウントダウン実装単方法_StartCountdown()
ある:
ViewModel.cs:
をclass ViewModel
{
private async void _StartCountdown()
{
Running = true;
// NOTE: UTC times used internally to ensure proper operation
// across Daylight Saving Time changes. An IValueConverter can
// be used to present the user a local time.
// NOTE: RemainingTime is the raw data. It may be desirable to
// use an IValueConverter to always round up to the nearest integer
// value for whatever is the least-significant component displayed
// (e.g. minutes, seconds, milliseconds), so that the displayed
// value doesn't reach the zero value until the timer has completed.
DateTime startTime = DateTime.UtcNow, endTime = startTime + Duration;
TimeSpan remainingTime, interval = TimeSpan.FromMilliseconds(100);
StartTime = startTime;
remainingTime = endTime - startTime;
while (remainingTime > TimeSpan.Zero)
{
RemainingTime = remainingTime;
if (RemainingTime < interval)
{
interval = RemainingTime;
}
// NOTE: arbitrary update rate of 100 ms (initialized above). This
// should be a value at least somewhat less than the minimum precision
// displayed (e.g. here it's 1/10th the displayed precision of one
// second), to avoid potentially distracting/annoying "stutters" in
// the countdown.
await Task.Delay(interval);
remainingTime = endTime - DateTime.UtcNow;
}
RemainingTime = TimeSpan.Zero;
StartTime = null;
Running = false;
}
private TimeSpan _duration;
public TimeSpan Duration
{
get { return _duration; }
set { _UpdateField(ref _duration, value); }
}
private DateTime? _startTime;
public DateTime? StartTime
{
get { return _startTime; }
private set { _UpdateField(ref _startTime, value); }
}
private TimeSpan _remainingTime;
public TimeSpan RemainingTime
{
get { return _remainingTime; }
private set { _UpdateField(ref _remainingTime, value); }
}
private bool _running;
public bool Running
{
get { return _running; }
private set { _UpdateField(ref _running, value, _OnRunningChanged); }
}
private void _OnRunningChanged(bool obj)
{
_startCountdownCommand.RaiseCanExecuteChanged();
}
private readonly DelegateCommand _startCountdownCommand;
public ICommand StartCountdownCommand { get { return _startCountdownCommand; } }
public ViewModel()
{
_startCountdownCommand = new DelegateCommand(_StartCountdown,() => !Running);
}
public event PropertyChangedEventHandler PropertyChanged;
private void _UpdateField<T>(ref T field, T newValue,
Action<T> onChangedCallback = null,
[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, newValue))
{
return;
}
T oldValue = field;
field = newValue;
onChangedCallback?.Invoke(oldValue);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
コメントに記載されているとおり、上記はそのまま動作しますが、特定の出力が必要な場合は、IValueConverter
の実装でユーザー固有のニーズに合わせて出力を調整すると便利です。
UtcToLocalConverter.cs:
class UtcToLocalConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
if (value is DateTime)
{
DateTime dateTime = (DateTime)value;
return dateTime.ToLocalTime();
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
if (value is DateTime)
{
DateTime dateTime = (DateTime)value;
return dateTime.ToUniversalTime();
}
return Binding.DoNothing;
}
}
TimeSpanRoundUpConverter.cs:
class TimeSpanRoundUpConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is TimeSpan && parameter is TimeSpan))
{
return Binding.DoNothing;
}
return RoundUpTimeSpan((TimeSpan)value, (TimeSpan)parameter);
}
private static TimeSpan RoundUpTimeSpan(TimeSpan value, TimeSpan roundTo)
{
if (value < TimeSpan.Zero) return RoundUpTimeSpan(-value, roundTo);
double quantization = roundTo.TotalMilliseconds, input = value.TotalMilliseconds;
double normalized = input/quantization;
int wholeMultiple = (int)normalized;
double fraction = normalized - wholeMultiple;
return TimeSpan.FromMilliseconds((fraction == 0 ? wholeMultiple : wholeMultiple + 1) * quantization);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
そしてもちろん、いくつかのXAMLは、UIを定義するところなし(ここではそれらのいくつかの例がありますコードエレメントは明示的にそれらのいずれかにアクセスする必要はありません)。
メインウィンドウxaml:
<Window x:Class="TestSO16748371CountdownTimer.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:l="clr-namespace:TestSO16748371CountdownTimer"
xmlns:s="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:ViewModel/>
</Window.DataContext>
<Window.Resources>
<l:UtcToLocalConverter x:Key="utcToLocalConverter1"/>
<l:TimeSpanRoundUpConverter x:Key="timeSpanRoundUpConverter1"/>
<s:TimeSpan x:Key="timeSpanRoundTo1">00:00:01</s:TimeSpan>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Duration: "/>
<TextBox Text="{Binding Duration}" Grid.Column="1"/>
<TextBlock Text="Start time:" Grid.Row="1"/>
<TextBlock Text="{Binding StartTime, Converter={StaticResource utcToLocalConverter1}}" Grid.Row="1" Grid.Column="1"/>
<TextBlock Text="Remaining time:" Grid.Row="2"/>
<TextBlock Text="{Binding RemainingTime,
StringFormat=hh\\:mm\\:ss,
Converter={StaticResource timeSpanRoundUpConverter1},
ConverterParameter={StaticResource timeSpanRoundTo1}}" Grid.Row="2" Grid.Column="1"/>
<Button Content="Start Countdown" Command="{Binding StartCountdownCommand}" Grid.Row="3" VerticalAlignment="Top"/>
</Grid>
</Window>
関連する問題
- 1. Javaでカウントダウンタイマーを作成するには
- 2. B4Androidでカウントダウンタイマーを作成するには
- 3. カウントダウンタイマーの作成方法は?
- 4. JSカウントダウンタイマーでプログレスバーを作成
- 5. Silverlightでカウントダウンタイマーを作成する
- 6. javascriptでカウントダウンタイマーを作成する方法
- 7. iPhoneアプリでカウントダウンタイマーを作成する
- 8. 私はカウントダウンタイマーを作成するとすぐにタイマーが終了すると私は別のカウントダウンタイマーが
- 9. WPFでレンダリングループを作成するには?
- 10. wpfでカスタムウィンドウクロムを作成するには?
- 11. カスタムWPFコレクションを作成するには?
- 12. WPFでラジアルメニューを作成するには?
- 13. wpfでメッセージボックスを作成するには
- 14. RxJS Observablesでカウントダウンタイマーを作成する方法は?
- 15. C#windowsアプリケーションフォームで複数のカウントダウンタイマーを作成する方法は?
- 16. 2つのカウントダウンタイマーを作るには?
- 17. JFrame内でのカウントダウンタイマーの作成
- 18. appengineでカウントダウンタイマーを作成するにはどうすればいいですか?
- 19. ユーザー定義番号を使用してカウントダウンタイマーを作成する
- 20. Swiftで複数のカウントダウンタイマーを作成する
- 21. php foreachループ内でjavascriptのカウントダウンタイマーを作成する
- 22. ボタンで15分のカウントダウンタイマーを作成する - javascript
- 23. Cocos2d-xでカウントダウンタイマーを作成する最も良い方法は何ですか?
- 24. 即時に完了ハンドラを使用してカウントダウンタイマーを作成する方法
- 25. Int入力からカウントダウンタイマーを作成しますか?
- 26. Javascriptのカウントダウンタイマーで2桁の数字を作成しますか?
- 27. WPFのビットマップであるUserControlを作成するには?
- 28. Javascriptで非常に簡単なカウントダウンタイマーを作るには?
- 29. WPFでプロパティを使用してカスタムシェイプを作成するには?
- 30. バックエンドでリセットされるRailsでのカウントダウンタイマーの作成