WPF(.NET 4)中是否有TimePicker控件?
我希望DatePicker控件能够显示数据或时间或两者,但似乎并非如此。其中任何一个都适合我的账单:
Wednesday, February 8th, 2012 2:27 pm
-OR:
2:27 pm
(我将与DatePicker一起使用)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~
更新(尝试安装扩展WPF控件后):
这么多/它听起来不应该那么容易。
当我尝试从中下载扩展WPF工具包时 http://wpftoolkit.codeplex.com/releases/view/71499我进入了下载对话框:
http://download.codeplex.com/site/pagenotfound?ReferenceId=f1704e1d-3152-4ecf-b2bb-ace62735bcbc
(注意“找不到页面”部分 - 没有下载)。
...然后我继续计划B并尝试下载/安装Nuget,这样我就可以通过这种方式获得扩展的WPF工具包(通过工具|扩展管理器|在线图库|更新(1)| NeGet包管理器|下载)。
我首先必须取消选中“保护我免受潜在恶意代码侵害”的方框(或类似的东西 - 我已经尝试过了(两次!)而没有取消选中该复选框,并且两次都崩溃了);然后(取消选中此框后)我在安装对话框中看到,“此扩展包含带有无效证书的数字签名。”
我还是继续,最后安装了Nuget。
因此,重新启动Visual Studio 2010后,我转到了Tools |库包管理器|软件包管理器控制台,但遇到错误:软件包管理器控制台需要PowerShell 2.0运行时,这在此计算机上未检测到。请从http://support.microsoft.com/kb/968929安装PowerShell 2.0并重新启动Visual Studio.rt Visual Studio。“
然后,当我去安装该更新(WindowsXP-KB968930-x86-ENG.exe)时,我得到了“更新/ update.exe应用程序无法在Win32模式下运行。”它未能继续。
Achhh !!!感觉像星期一!
答案 0 :(得分:32)
WPF 4.0不提供开箱即用的DateTimePicker。
<强>更新强> 我在最近的项目中使用了扩展 WPF工具包http://wpftoolkit.codeplex.com/,它包含了一个不错的DateTimePicker控件 - http://wpftoolkit.codeplex.com/wikipage?title=DateTimePicker&referringTitle=Home。
抱歉这种不准确。
答案 1 :(得分:6)
在Codeplex上查看扩展的WPF工具包DateTimeUpDown(或related SO post )。
答案 2 :(得分:1)
WPF没有正式制作一个,但你可以查看这个人做了什么:
WPF Time Picker
或者你可以自己制作
答案 3 :(得分:0)
我的简单时间控制解决方案
TimeControl.xaml
<UserControl x:Class="Infra.UICommon.Controls.TimeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Infra.UICommon.Controls"
mc:Ignorable="d"
Height="Auto" Width="Auto" x:Name="UserControl"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="LayoutRoot" Width="Auto" Height="Auto" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*"/>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.2*"/>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.2*"/>
<ColumnDefinition Width="0.05*"/>
<ColumnDefinition Width="0.2*"/>
</Grid.ColumnDefinitions>
<!-- Hours -->
<Grid x:Name="hours" Focusable="True" MouseWheel="OnMouseWheel" >
<TextBox x:Name="hh" TextWrapping="Wrap" Text="{Binding Path=Hours, ElementName=UserControl, Mode=Default}"
PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput" DataObject.Pasting="OnTextPasting"
TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0"/>
</Grid>
<!-- Separator ':' -->
<Grid Grid.Column="1">
<TextBox IsReadOnly="True" x:Name="sep1" TextWrapping="Wrap" VerticalAlignment="Center" Text=":" TextAlignment="Center" BorderThickness="0"/>
</Grid>
<!-- Minutes -->
<Grid Grid.Column="2" x:Name="minutes" Focusable="True" MouseWheel="OnMouseWheel">
<TextBox x:Name="mm" TextWrapping="Wrap" Text="{Binding Path=Minutes, ElementName=UserControl, Mode=Default}"
PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput" DataObject.Pasting="OnTextPasting"
TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0" />
</Grid>
<!-- Separator ':' -->
<Grid Grid.Column="3">
<TextBox IsReadOnly="True" x:Name="sep2" TextWrapping="Wrap" VerticalAlignment="Center" Text=":" TextAlignment="Center" BorderThickness="0"/>
</Grid>
<!-- Seconds -->
<Grid Grid.Column="4" Name="seconds" Focusable="True" MouseWheel="OnMouseWheel">
<TextBox x:Name="ss" TextWrapping="Wrap" Text="{Binding Path=Seconds, ElementName=UserControl, Mode=Default}"
PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput" DataObject.Pasting="OnTextPasting"
TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0" />
</Grid>
<!-- Separator ':' -->
<Grid Grid.Column="5">
<TextBox IsReadOnly="True" x:Name="sep3" TextWrapping="Wrap" VerticalAlignment="Center" Text=":" TextAlignment="Center" BorderThickness="0"/>
</Grid>
<!-- Milliseconds -->
<Grid Grid.Column="6" Name="miliseconds" Focusable="True" MouseWheel="OnMouseWheel">
<TextBox x:Name="ff" TextWrapping="Wrap" Text="{Binding Path=Milliseconds, ElementName=UserControl, Mode=Default}"
PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput" DataObject.Pasting="OnTextPasting"
TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0" />
</Grid>
</Grid>
</UserControl>
TimeControl.xaml.cs(后面的代码)
namespace Infra.UICommon.Controls
{
/// <summary>
/// Interaction logic for TimeControl.xaml
/// </summary>
public partial class TimeControl : UserControl
{
public TimeControl()
{
InitializeComponent();
}
private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
TimeControl control = obj as TimeControl;
var newTime = (TimeSpan)e.NewValue;
control.Hours = newTime.Hours;
control.Minutes = newTime.Minutes;
control.Seconds = newTime.Seconds;
control.Milliseconds = newTime.Milliseconds;
}
private static void OnTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
TimeControl control = obj as TimeControl;
control.Value = new TimeSpan(0, control.Hours, control.Minutes, control.Seconds, control.Milliseconds);
}
public TimeSpan Value
{
get { return (TimeSpan)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(TimeSpan), typeof(TimeControl),
new FrameworkPropertyMetadata(DateTime.Now.TimeOfDay, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnValueChanged)));
public int Hours
{
get { return (int)GetValue(HoursProperty); }
set { SetValue(HoursProperty, value); }
}
public static readonly DependencyProperty HoursProperty =
DependencyProperty.Register("Hours", typeof(int), typeof(TimeControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));
public int Minutes
{
get { return (int)GetValue(MinutesProperty); }
set { SetValue(MinutesProperty, value); }
}
public static readonly DependencyProperty MinutesProperty =
DependencyProperty.Register("Minutes", typeof(int), typeof(TimeControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));
public int Seconds
{
get { return (int)GetValue(SecondsProperty); }
set { SetValue(SecondsProperty, value); }
}
public static readonly DependencyProperty SecondsProperty =
DependencyProperty.Register("Seconds", typeof(int), typeof(TimeControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));
public int Milliseconds
{
get { return (int)GetValue(MillisecondsProperty); }
set { SetValue(MillisecondsProperty, value); }
}
public static readonly DependencyProperty MillisecondsProperty =
DependencyProperty.Register("Milliseconds", typeof(int), typeof(TimeControl),
new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));
private Tuple<int, int> GetMaxAndCurentValues(String name)
{
int maxValue = 0;
int currValue = 0;
switch (name)
{
case "ff":
maxValue = 1000;
currValue = Milliseconds;
break;
case "ss":
maxValue = 60;
currValue = Seconds;
break;
case "mm":
maxValue = 60;
currValue = Minutes;
break;
case "hh":
maxValue = 24;
currValue = Hours;
break;
}
return new Tuple<int, int>(maxValue, currValue);
}
private void UpdateTimeValue(String name, int delta)
{
var values = GetMaxAndCurentValues(name);
int maxValue = values.Item1;
int currValue = values.Item2;
// Set new value
int newValue = currValue + delta;
if (newValue == maxValue)
{
newValue = 0;
}
else if (newValue < 0)
{
newValue += maxValue;
}
switch (name)
{
case "ff":
Milliseconds = newValue;
break;
case "ss":
Seconds = newValue;
break;
case "mm":
Minutes = newValue;
break;
case "hh":
Hours = newValue;
break;
}
}
private void OnKeyDown(object sender, KeyEventArgs args)
{
try
{
int delta = 0;
String name = ((TextBox)sender).Name;
if (args.Key == Key.Up) { delta = 1; }
else if (args.Key == Key.Down) { delta = -1; }
UpdateTimeValue(name, delta);
}
catch { }
}
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
try
{
var g = (Grid)(sender);
var value = g.Children.OfType<TextBox>().FirstOrDefault();
UpdateTimeValue(value.Name, e.Delta / Math.Abs(e.Delta));
}
catch { }
}
private Boolean IsTextAllowed(String name, String text)
{
try
{
foreach (Char c in text.ToCharArray())
{
if (Char.IsDigit(c) || Char.IsControl(c)) continue;
else return false;
}
var values = GetMaxAndCurentValues(name);
int maxValue = values.Item1;
int newValue = Convert.ToInt32(text);
if (newValue < 0 || newValue >= (Int32)maxValue)
{
return false;
}
} catch
{
return false;
}
return true;
}
// Use the OnPreviewTextInput to respond to key presses
private void OnPreviewTextInput(Object sender, TextCompositionEventArgs e)
{
try
{
var tb = (TextBox)sender;
e.Handled = !IsTextAllowed(tb.Name, tb.Text + e.Text);
}
catch { }
}
// Use the DataObject.Pasting Handler
private void OnTextPasting(object sender, DataObjectPastingEventArgs e)
{
try
{
String name = ((TextBox)sender).Name;
if (e.DataObject.GetDataPresent(typeof(String)))
{
String text = (String)e.DataObject.GetData(typeof(String));
if (!IsTextAllowed(name, text)) e.CancelCommand();
}
else e.CancelCommand();
}
catch { }
}
}
}
用法:
<ctrl:TimeControl Value="{Binding StartTime, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="startTime"/>
其中“ ctrl”是TimeControl所在的名称空间,“ StartTime”是“ TimeSpan”类型的属性。
xmlns:ctrl="clr-namespace:Infra.UICommon.Controls;assembly=Infra.UICommon"
希望这会有所帮助)
p.s。 唯一未在此处处理的是'backspace'和'delete'键。