wpf里有日期选择控件,但没有时间选择控件。其他地方也有类似的,但效果并不太好,而且复杂。所以就自己写了个。参考codeproject上的。

分两部分。

第一部分是.cs文件。也就是control控件的内部逻辑。定义相关属性,以及委托。主要是通过自定义属性以及各个属性(时分秒)之间的联系来进行绑定的。代码如下:

using System;
using System.Windows;
using System.Windows.Controls; namespace CustomControls
{
/// <summary>
/// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
///
/// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
/// 元素中:
///
/// xmlns:MyNamespace="clr-namespace:时间选择控件"
///
///
/// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
/// 元素中:
///
/// xmlns:MyNamespace="clr-namespace:时间选择控件;assembly=时间选择控件"
///
/// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
/// 并重新生成以避免编译错误:
///
/// 在解决方案资源管理器中右击目标项目,然后依次单击
/// “添加引用”->“项目”->[浏览查找并选择此项目]
///
///
/// 步骤 2)
/// 继续操作并在 XAML 文件中使用控件。
///
/// <MyNamespace:TimeSpanPicker/>
///
/// </summary>
public class TimeSpanPicker : Control
{
static TimeSpanPicker()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeSpanPicker), new FrameworkPropertyMetadata(typeof(TimeSpanPicker)));
} /// <summary>
/// 时间控制方法,自动计算时间
/// </summary>
/// <param name="e"></param>
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e); if (e.Property == HourProperty)
{
int hour = (int)e.NewValue;
if (hour == 24)
{
SetValue(HourProperty, 23);
}
else if (hour == -1)
{
SetValue(HourProperty, 0);
}
//else
SetValue(TimeSpanProperty, new TimeSpan(Hour, TimeSpan.Minutes, TimeSpan.Seconds));
}
else if (e.Property == MinuteProperty)
{
int minute = (int)e.NewValue;
if (minute == -1)
{
if (Hour == 0)
{
SetValue(MinuteProperty, 0);
}
else
{
SetValue(MinuteProperty, 59);
SetValue(HourProperty, Hour - 1);
}
}
else if (minute == 60)
{
if (Hour == 24)
{
SetValue(MinuteProperty, 59);
}
else
{
SetValue(MinuteProperty, 0);
SetValue(HourProperty, Hour + 1);
}
}
//else
SetValue(TimeSpanProperty, new TimeSpan(TimeSpan.Hours, Minute, TimeSpan.Seconds));
}
else if (e.Property == SecondProperty)
{
int second = (int)e.NewValue;
if (second == -1)
{
if (Minute > 0 || Hour > 0)
{
SetValue(SecondProperty, 59);
SetValue(MinuteProperty, Minute - 1);
}
else
{
SetValue(SecondProperty, 0);
}
}
else if (second == 60)
{ SetValue(SecondProperty, 0);
SetValue(MinuteProperty, Minute + 1); }
//设置时间
SetValue(TimeSpanProperty, new TimeSpan(TimeSpan.Hours, TimeSpan.Minutes, Second));
}
else if (e.Property == TimeSpanProperty)
{
TimeSpan ts = (TimeSpan)e.NewValue; SetValue(HourProperty, ts.Hours);
SetValue(MinuteProperty, ts.Minutes);
SetValue(SecondProperty, ts.Seconds);
}
} public bool IsReadOnly
{
get { return (bool)GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
} // Using a DependencyProperty as the backing store for IsReadOnly. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(TimeSpanPicker), new PropertyMetadata(false)); public TimeSpan TimeSpan
{
get { return (TimeSpan)GetValue(TimeSpanProperty); }
set { SetValue(TimeSpanProperty, value); }
} public static readonly DependencyProperty TimeSpanProperty =
DependencyProperty.Register("TimeSpan", typeof(TimeSpan), typeof(TimeSpanPicker), new PropertyMetadata(TimeSpan.Zero)); public int Hour
{
get { return (int)GetValue(HourProperty); }
set { SetValue(HourProperty, value); }
} public static readonly DependencyProperty HourProperty =
DependencyProperty.Register("Hour", typeof(int), typeof(TimeSpanPicker), new PropertyMetadata(0)); public int Minute
{
get { return (int)GetValue(MinuteProperty); }
set { SetValue(MinuteProperty, value); }
} public static readonly DependencyProperty MinuteProperty =
DependencyProperty.Register("Minute", typeof(int), typeof(TimeSpanPicker), new PropertyMetadata(0)); public int Second
{
get { return (int)GetValue(SecondProperty); }
set { SetValue(SecondProperty, value); }
} public static readonly DependencyProperty SecondProperty =
DependencyProperty.Register("Second", typeof(int), typeof(TimeSpanPicker), new PropertyMetadata(0)); }
}

另外,有时候时间选择控件的前台是不希望让用户输入字符及符号的。只能让用户输入int型的时分秒。所以定义了一个numbericTextbox。也就是只能输入数字的文本框。代码如下:

using System;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input; namespace CustomControls
{
public class NumbiricTextBox : TextBox
{
private static Regex regex = new Regex("[0-9]+");
public NumbiricTextBox()
{
SetValue(InputMethod.IsInputMethodEnabledProperty, false);//禁用输入法
DataObject.AddPastingHandler(this, TextBoxPasting);//粘贴时候判断
this.MaxLength = 2;//设置长度,避免过多输入
} /// <summary>
/// 输入判定,只能输入数字 大于0
/// </summary>
/// <param name="e"></param>
protected override void OnPreviewTextInput(TextCompositionEventArgs e)
{
e.Handled = !regex.IsMatch(e.Text);
} /// <summary>
/// 滚轮改变值大小
/// </summary>
/// <param name="e"></param>
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
base.OnPreviewMouseWheel(e);
if (!regex.IsMatch(this.Text))
{
return;
}
e.Handled = !regex.IsMatch(this.Text);
var x = e.Source;
if (x != null && x is NumbiricTextBox)
{
NumbiricTextBox tbx = x as NumbiricTextBox;
if (e.Delta > 0)
{
tbx.Text = (int.Parse(tbx.Text) + 1).ToString();
}
else
{
tbx.Text = (int.Parse(tbx.Text) - 1).ToString();
}
}
}
//保证值不为空····························
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
if (string.IsNullOrWhiteSpace(this.Text))
{
this.Text = "0";
}
}
/// <summary>
/// 粘贴事件检查
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
String text = (String)e.DataObject.GetData(typeof(String));
if (!regex.IsMatch(text))
{
e.CancelCommand();
}
}
else
{
e.CancelCommand();
}
} }
}

我们定义了控件,但还是不能用的,必须给控件模板才能 用。控件模板就是根据需要来自定义样式了。我做了个简单的。xaml代码如下:

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls">
<!--<local:Hour2StringConverter x:Key="HourConverter"/>--> <Style TargetType="{x:Type local:TimeSpanPicker}"> <Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:TimeSpanPicker}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal">
<local:NumbiricTextBox x:Name="hourTbx" MinWidth="20" Text="{Binding Path=Hour, RelativeSource={RelativeSource TemplatedParent},UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Height="Auto" >
</local:NumbiricTextBox>
<Label Content=":" VerticalAlignment="Center" Height="Auto"/>
<local:NumbiricTextBox MinWidth="20" Text="{Binding Path=Minute,RelativeSource={RelativeSource TemplatedParent},UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Height="Auto"></local:NumbiricTextBox>
<Label Content=":" VerticalAlignment="Center" Height="Auto"/>
<local:NumbiricTextBox MinWidth="20" Text="{Binding Path=Second,RelativeSource={RelativeSource TemplatedParent},UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" Height="Auto"></local:NumbiricTextBox>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

这样就能用了。

调用的时候可以写个测试程序:

前台xaml:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls" x:Class="CustomControls.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:NumbiricTextBox HorizontalAlignment="Left" Margin="74,183,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="69" Width="257" />
<local:TimeSpanPicker HorizontalAlignment="Left" Margin="62,69,0,0" VerticalAlignment="Top" Height="28" Width="180" x:Name="timePicker" />
<Button Content="获取时间" HorizontalAlignment="Left" Margin="62,117,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<Label x:Name="lb1" Content="Label" HorizontalAlignment="Left" Margin="164,117,0,0" VerticalAlignment="Top"/>
<Button Content="设置时间" HorizontalAlignment="Left" Margin="51,32,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/> </Grid>
</Window>

后台cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 CustomControls
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
} private void Button_Click(object sender, RoutedEventArgs e)
{
lb1.Content = timePicker.TimeSpan.ToString();
} private void Button_Click_1(object sender, RoutedEventArgs e)
{
timePicker.SetValue(TimeSpanPicker.TimeSpanProperty, new TimeSpan(DateTime.Now.Hour,DateTime.Now.Minute,DateTime.Now.Second));
} }
}

是不是很简单呢?

效果如下:

源码地址:http://files.cnblogs.com/files/lizhijian/%E6%97%B6%E9%97%B4%E9%80%89%E6%8B%A9%E6%8E%A7%E4%BB%B6.rar

感谢每一位阅读此篇博客的人,希望可以帮助到你。

wpf timePicker 时间选择控件的更多相关文章

  1. 2019-8-30-win10-uwp-好看的时间选择控件

    title author date CreateTime categories win10 uwp 好看的时间选择控件 lindexi 2019-08-30 08:57:20 +0800 2018-0 ...

  2. win10 uwp 好看的时间选择控件

    本文告诉大家我找到的好看的时间选择控件 先给大家看一下图,然后就知道我说的是什么 首先需要安装 Nuget ,搜索 DeanChalk.UWP.TimePicker 或输入Install-Packag ...

  3. WPF中Ribbon控件的使用

    这篇博客将分享如何在WPF程序中使用Ribbon控件.Ribbon可以很大的提高软件的便捷性. 上面截图使Outlook 2010的界面,在Home标签页中,将所属的Menu都平铺的布局,非常容易的可 ...

  4. WPF 调用WinForm控件

    WPF可以使用WindowsFormsHost控件做为容器去显示WinForm控件,类似的用法网上到处都是,就是拖一个WindowsFormsHost控件winHost1到WPF页面上,让后设置win ...

  5. InteropBitmap指定内存,绑定WPF的Imag控件时刷新问题。

    1.InteropBitmap指定内存,绑定WPF的Imag控件的Source属性 创建InteropBitmap的时候,像素的格式必须为PixelFormats.Bgr32, 如果不是的话在绑定到I ...

  6. 在WPF程序中将控件所呈现的内容保存成图像(转载)

    在WPF程序中将控件所呈现的内容保存成图像 转自:http://www.cnblogs.com/TianFang/archive/2012/10/07/2714140.html 有的时候,我们需要将控 ...

  7. 【WPF】监听WPF的WebBrowser控件弹出新窗口的事件

    原文:[WPF]监听WPF的WebBrowser控件弹出新窗口的事件 WPF中自带一个WebBrowser控件,当我们使用它打开一个网页,例如百度,然后点击它其中的链接时,如果这个链接是会弹出一个新窗 ...

  8. 在WPF的WebBrowser控件中抑制脚本错误

    原文:在WPF的WebBrowser控件中抑制脚本错误 今天用WPF的WebBrowser控件的时候,发现其竟然没有ScriptErrorsSuppressed属性,导致其到处乱弹脚本错误的对话框,在 ...

  9. 基于zepto的移动端日期和时间选择控件

    前段时间给大家分享过一个基于jQuery Mobile的移动端日期时间拾取器,大家反应其由于加载过大的插件导致影响调用速度.那么今天我把从网络上搜集到的两个适合移动端应用的日期和时间选择插件分享给大家 ...

随机推荐

  1. 深入理解 react-router 路由系统

    作者:范洪春链接:https://zhuanlan.zhihu.com/p/20381597来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 在 web 应用开发中,路由 ...

  2. hihoCoder #1082 : 然而沼跃鱼早就看穿了一切(字符串处理)

    #1082 : 然而沼跃鱼早就看穿了一切 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 fjxmlhx每天都在被沼跃鱼刷屏,因此他急切的找到了你希望你写一个程序屏蔽所有句 ...

  3. [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)

    以后似乎终于不用去学后缀数组的倍增搞法||DC3等blablaSXBK的方法了= = 定义(来自关于后缀数组的那篇国家集训队论文..) 后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列S ...

  4. JAVA爬虫实践(实践一:知乎)

    爬虫顺序 1.分析网站网络请求 通过浏览器F12开发者工具查看网站的内容获取方式. 2.模拟HTTP请求,获取网页内容. 可以采用HttpClient,利用JAVA HttpClient工具可以模拟H ...

  5. 【JAVA】SWING_ 界面风格

    在java中,界面外观的管理是由UIManager类来管理的.不同的系统上安装的外观不一样 ,默认的是java的跨平台外观. 1.获取系统所有外观 import javax.swing.*; impo ...

  6. 2017年 JavaScript 框架回顾 -- React生态系统

    前一篇文章中,我们介绍了2017年 JavaScript 框架的整体情况.我们也了解到在众多的前端框架中,目前最为庞大又在快速增长的当属 React 了,本文就来重点介绍 React 的生态系统. 首 ...

  7. python动态类型

    在python中,省去了变量声明的过程,在引用变量时,往往一个简单的赋值语句就同时完成了,声明变量类型,变量定义和关联的过程,那么python的变量到底是怎样完成定义的呢? 动态类型 python使用 ...

  8. memcached经典问题和现象

    缓存刷新时间集中问题 某个缓存失效了,导致其他节点的缓存命中率下降, 缓存中缺失的数据 去数据库查询.短时间内,会造成数据库服务器崩溃 需要将缓存失效时间离散分布在访问量比较低的时间段 multige ...

  9. 利用PHPExcel导出Excel并设置Excel格式以及数据源

    浏览:23969 发布日期:2013/07/24 分类:技术分享 代码有点长,读起来有点累.先来个截图 导出的Excel太宽了,所以将后面的列宽重新调整了再截的图 功能包括: 1.设置单元格格式,包括 ...

  10. tp5 url 线上访问 在nginx 上 出现404错误,解决办法(1.80nginx 配置 pathInfo)

      对于ThinkPHP的URL访问路劲如:http://域名/index.php/Index/BlogTest/read,原先的Nginx的是不支持的pathinfo路劲的,导致你在thinkPHP ...