我的Windows 8.1(Windows应用商店)应用需要 TimeSpanPicker 控件。我无法在Windows 8工具箱中找到它。如果控件已经可用,请与控件共享任何链接,或者帮助我从头开始构建它。
我已经在线搜索了解决方案,但TimeSpanPicker控件仅适用于Windows Phone而不适用于Windows 8。
如何实现循环控制UI来实现我自己的TimeSpanPicker?
答案 0 :(得分:0)
这可能是你的幸运日。我刚刚为时间码创建了一个微调器,我使用了timepan作为它的值。 这有点粗糙,但它完成了工作。无论如何,它可能会给你如何建立自己的想法。
注意这是作为自定义控件构建的。我想用户控件也可以工作。
XAML:
<Style TargetType="{x:Type local:TimeCodeUpDown}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TimeCodeUpDown}">
<Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
SnapsToDevicePixels="True"
>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
HorizontalAlignment="Left"
Padding="1"
>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBox x:Name="HoursText"
BorderThickness="0"
VerticalAlignment="Center"
Width="Auto"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Hours, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="1"/>
<TextBox x:Name="HoursSeparator"
BorderThickness="0"
VerticalAlignment="Center"
Text=":"/>
<TextBox x:Name="MinutesText"
BorderThickness="0"
VerticalAlignment="Center"
Width="Auto"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Minutes, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="2"/>
<TextBox x:Name="MinutesSeparator"
BorderThickness="0"
VerticalAlignment="Center"
Text=":"/>
<TextBox x:Name="SecondsText"
BorderThickness="0"
VerticalAlignment="Center"
Width="Auto"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Seconds, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="3"/>
<TextBox x:Name="SecondsSeparator"
BorderThickness="0"
VerticalAlignment="Center"
Text=":"/>
<TextBox x:Name="FramesText"
BorderThickness="0"
VerticalAlignment="Center"
Width="Auto"
Text="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Frames, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="4"/>
<Grid x:Name="ButtonGrid"
Margin="3,0,0,0"
Width="10">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button x:Name="UpButton" Grid.Row="0"
BorderThickness="0.5" Margin="0,0,0,0.5"
Background="Transparent">
<Path Stroke="Transparent" Fill="Black" Data="M 1 3.5 L 2.5 1 L 4 3.5 Z"/>
</Button>
<Button x:Name="DownButton"
Grid.Row="1"
BorderThickness="0.5" Margin="0,0.5,0,0" Background="Transparent">
<Path Stroke="Transparent" Fill="Black" Data="M 1 1 L 2.5 4 L 4 1 Z"/>
</Button>
</Grid>
</StackPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Stv.AutoCatch.Desktop.Client.Infrastructure.Controls
{
/// <summary>
/// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
///
/// Step 1a) Using this custom control in a XAML file that exists in the current project.
/// Add this XmlNamespace attribute to the root element of the markup file where it is
/// to be used:
///
/// xmlns:MyNamespace="clr-namespace:Stv.AutoCatch.Desktop.Client.Infrastructure.Controls"
///
///
/// Step 1b) Using this custom control in a XAML file that exists in a different project.
/// Add this XmlNamespace attribute to the root element of the markup file where it is
/// to be used:
///
/// xmlns:MyNamespace="clr-namespace:Stv.AutoCatch.Desktop.Client.Infrastructure.Controls;assembly=Stv.AutoCatch.Desktop.Client.Infrastructure.Controls"
///
/// You will also need to add a project reference from the project where the XAML file lives
/// to this project and Rebuild to avoid compilation errors:
///
/// Right click on the target project in the Solution Explorer and
/// "Add Reference"->"Projects"->[Browse to and select this project]
///
///
/// Step 2)
/// Go ahead and use your control in the XAML file.
///
/// <MyNamespace:TimeCodeUpDown/>
///
/// </summary>
public class TimeCodeUpDown : Control
{
TextBox _lastFocusedTextBox;
internal TimeSpan InternalTime
{
get { return _internalTime; }
}
TimeSpan _internalTime = TimeSpan.Zero;
static TimeCodeUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeCodeUpDown), new FrameworkPropertyMetadata(typeof(TimeCodeUpDown)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Button upButton = (Button)base.GetTemplateChild("UpButton");
Button downButton = (Button)base.GetTemplateChild("DownButton");
upButton.Click += upButton_Click;
downButton.Click += downButton_Click;
TextBox hoursText = (TextBox)base.GetTemplateChild("HoursText");
hoursText.GotFocus += _hoursText_GotFocus;
TextBox minutesText = (TextBox)base.GetTemplateChild("MinutesText");
minutesText.GotFocus += _minutesText_GotFocus;
TextBox secondsText = (TextBox)base.GetTemplateChild("SecondsText");
secondsText.GotFocus += _secondsText_GotFocus;
TextBox framesText = (TextBox)base.GetTemplateChild("FramesText");
framesText.GotFocus += _framesText_GotFocus;
}
void _framesText_GotFocus(object sender, RoutedEventArgs e)
{
_lastFocusedTextBox = (TextBox)sender;
}
void _secondsText_GotFocus(object sender, RoutedEventArgs e)
{
_lastFocusedTextBox = (TextBox)sender;
}
void _minutesText_GotFocus(object sender, RoutedEventArgs e)
{
_lastFocusedTextBox = (TextBox)sender;
}
void _hoursText_GotFocus(object sender, RoutedEventArgs e)
{
_lastFocusedTextBox = (TextBox)sender;
}
void downButton_Click(object sender, RoutedEventArgs e)
{
if (_lastFocusedTextBox != null)
{
if (_lastFocusedTextBox.Name.Equals("HoursText"))
{
if (this.Hours > 0)
this.Hours--;
else if (this.Hours == 0)
this.Hours = 23;
}
if (_lastFocusedTextBox.Name.Equals("MinutesText"))
{
if (this.Minutes > 0)
this.Minutes--;
else if (this.Minutes == 0)
this.Minutes = 59;
}
if (_lastFocusedTextBox.Name.Equals("SecondsText"))
{
if (this.Seconds > 0)
this.Seconds--;
else if (this.Seconds == 0)
this.Seconds = 59;
}
if (_lastFocusedTextBox.Name.Equals("FramesText"))
{
if (this.Frames > 0)
this.Frames--;
else if (this.Frames == 0)
this.Frames = 24;
}
}
}
void upButton_Click(object sender, RoutedEventArgs e)
{
if (_lastFocusedTextBox != null)
{
if (_lastFocusedTextBox.Name.Equals("HoursText"))
{
if (this.Hours < 23)
this.Hours++;
else if (this.Hours == 23)
this.Hours = 0;
}
if (_lastFocusedTextBox.Name.Equals("MinutesText"))
{
if (this.Minutes < 59)
this.Minutes++;
else if (this.Minutes == 59)
this.Minutes = 0;
}
if (_lastFocusedTextBox.Name.Equals("SecondsText"))
{
if (this.Seconds < 59)
this.Seconds++;
else if (this.Seconds == 59)
this.Seconds = 0;
}
if (_lastFocusedTextBox.Name.Equals("FramesText"))
{
if (this.Frames < 24)
this.Frames++;
else if (this.Frames == 24)
this.Frames = 0;
}
}
}
public TimeSpan TimeValue
{
get { return (TimeSpan)GetValue(TimeValueProperty); }
set { SetValue(TimeValueProperty, value); }
}
// Using a DependencyProperty as the backing store for TimeValue. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TimeValueProperty =
DependencyProperty.Register("TimeValue", typeof(TimeSpan), typeof(TimeCodeUpDown), new PropertyMetadata(TimeSpan.Zero, new PropertyChangedCallback(OnTimeValueChanged)));
private static void OnTimeValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = (TimeCodeUpDown)d;
TimeSpan newValue = (TimeSpan)e.NewValue;
if (newValue < TimeSpan.Zero || newValue >= TimeSpan.FromDays(1)) // ensure TimeSpan is less than 1 day and not negative.
newValue = new TimeSpan(0, newValue.Hours, newValue.Minutes, newValue.Seconds, newValue.Milliseconds);
if(!instance._internalTime.Equals(newValue))
{
// we are being changed from outside the control.
var absoluteTime = Convert.ToInt64(25 * newValue.TotalSeconds);
instance.Hours = Convert.ToInt32((absoluteTime / 90000) % 24);
instance.Minutes = Convert.ToInt32((absoluteTime - (90000 * instance.Hours)) / 1500);
instance.Seconds = Convert.ToInt32(((absoluteTime - (1500 * instance.Minutes) - (90000 * instance.Hours)) / 25));
instance.Frames = Convert.ToInt32(absoluteTime - (25 * instance.Seconds) - (1500 * instance.Minutes) - (90000 * instance.Hours));
}
}
//internal ICommand
public int Hours
{
get { return (int)GetValue(HoursProperty); }
set { SetValue(HoursProperty, value); }
}
// Using a DependencyProperty as the backing store for Hours. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HoursProperty =
DependencyProperty.Register("Hours", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnHoursChanged)));
private static void OnHoursChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = (TimeCodeUpDown)d;
TimeSpan newTime =
new TimeSpan(0, (int)e.NewValue, instance.TimeValue.Minutes, instance.TimeValue.Seconds, instance.TimeValue.Milliseconds);
instance._internalTime = newTime;
instance.TimeValue = newTime;
}
public int Minutes
{
get { return (int)GetValue(MinutesProperty); }
set { SetValue(MinutesProperty, value); }
}
// Using a DependencyProperty as the backing store for Minutes. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MinutesProperty =
DependencyProperty.Register("Minutes", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnMinutesChanged)));
private static void OnMinutesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = (TimeCodeUpDown)d;
TimeSpan newTime =
new TimeSpan(0, instance.TimeValue.Hours, (int)e.NewValue, instance.TimeValue.Seconds, instance.TimeValue.Milliseconds);
instance._internalTime = newTime;
instance.TimeValue = newTime;
}
public int Seconds
{
get { return (int)GetValue(SecondsProperty); }
set { SetValue(SecondsProperty, value); }
}
// Using a DependencyProperty as the backing store for Seconds. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SecondsProperty =
DependencyProperty.Register("Seconds", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnSecondsChanged)));
private static void OnSecondsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = (TimeCodeUpDown)d;
TimeSpan newTime =
new TimeSpan(0, instance.TimeValue.Hours, instance.TimeValue.Minutes, (int)e.NewValue, instance.TimeValue.Milliseconds);
instance._internalTime = newTime;
instance.TimeValue = newTime;
}
public int Frames
{
get { return (int)GetValue(FramesProperty); }
set { SetValue(FramesProperty, value); }
}
// Using a DependencyProperty as the backing store for Frames. This enables animation, styling, binding, etc...
public static readonly DependencyProperty FramesProperty =
DependencyProperty.Register("Frames", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnFramesChanged)));
private static void OnFramesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = (TimeCodeUpDown)d;
TimeSpan newTime =
new TimeSpan(0, instance.TimeValue.Hours, instance.TimeValue.Minutes, instance.TimeValue.Seconds, (int)e.NewValue * 40);
instance._internalTime = newTime;
instance.TimeValue = newTime;
}
}
}