wpf裏有日期選擇控件,但沒有時間選擇控件。其餘地方也有相似的,但效果並不太好,並且複雜。因此就本身寫了個。參考codeproject上的。html
分兩部分。app
第一部分是.cs文件。也就是control控件的內部邏輯。定義相關屬性,以及委託。主要是經過自定義屬性以及各個屬性(時分秒)之間的聯繫來進行綁定的。代碼以下:ide
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代碼以下:this
<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>
這樣就能用了。spa
調用的時候能夠寫個測試程序:code
前臺xaml:xml
<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文件:htm
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)); } } }
是否是很簡單呢?blog
效果以下:
源碼地址: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
感謝每一位閱讀此篇博客的人,但願能夠幫助到你。