在开发音乐相关的应用程序时,经常需要用户能够输入音乐轨道上的时间点。传统的TextBox控件虽然可以完成这项任务,但并不理想,因为它缺乏对时间格式的特定支持。为了解决这个问题,决定在WPF技术栈中实现一个专门的时间输入控件。这个控件不是作为一个独立的控件存在,而是以行为(Behavior)的形式集成到现有的TextBox控件中,这样可以利用TextBox控件的所有样式,并且可以灵活地应用到其他场景中。
最近,为这个控件增加了对双精度浮点数(double)的支持。这个改进是一个正在进行的工作,随着时间的推移,将会添加更多在初始版本中没有的功能。特别是,计划处理粘贴操作,但这在当前版本中尚未实现。
设计上,创建了一个单独的类,但这个类包含两个非常不同的部分,分别以静态(static)和实例(instance)代码实现。在行为(Behavior)的实现中,通常会只实现静态部分,并使用静态事件处理器。但在这种情况下,认为将代码分开会更好。
静态部分的代码如下:
public static readonly DependencyProperty MaxTimeProperty =
DependencyProperty.RegisterAttached(
"MaxTime",
typeof(string),
typeof(TimeSpanTextBoxBehaviour),
new UIPropertyMetadata(null, OnMaxTimeChanged));
public static string GetMaxTime(Control o)
{
return (string)o.GetValue(MaxTimeProperty);
}
public static void SetMaxTime(Control o, string value)
{
o.SetValue(MaxTimeProperty, value);
}
private static void OnMaxTimeChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs e)
{
var timeTextBoxBehaviour = GetTimeTextBoxBehaviour(dependencyObject);
var timeString = (string)e.NewValue;
var timeSpan = TimeSpanParse(timeString, false);
timeTextBoxBehaviour.MaxTimeSpanChanged(timeSpan);
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.RegisterAttached(
"Value",
typeof(TimeSpan),
typeof(TimeSpanTextBoxBehaviour),
new FrameworkPropertyMetadata(TimeSpan.Zero,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged));
public static TimeSpan GetValue(Control o)
{
return (TimeSpan)o.GetValue(ValueProperty);
}
public static void SetValue(Control o, TimeSpan value)
{
o.SetValue(ValueProperty, value);
}
这段代码定义了两个依赖属性:MaxTime和Value。MaxTime用于设置时间的最大值,而Value用于获取和设置当前的时间值。
对于计时器来说,如果需要提供格式的数据类似于社会安全号码,那么实现可能会更简单。只要在保存的社会安全号码中包含"-",就不需要ValueProperty。
目前,还没有实现向用户报告错误的功能,特别是当按下无效键时。只有数字键和其他一些键被支持,代码会忽略输入。通常在无效输入时会发出哔声,但这可能会让一些用户感到不适。考虑可能提供一个接口,允许绑定到一个命令来处理这些输入问题,对此很感兴趣。