2009-12-02 8 views
17

Ich bin auf der Suche nach einer einfachen für WPF-Picker Steuer Zeit.Was ist derzeit der beste, freie Zeitauswahl für WPF?

  • Ich habe festgestellt, dieses gefunden:

http://marlongrech.wordpress.com/2007/11/18/time-picker/

aber es hat einige Probleme z.B. Sie können nicht "00" eingeben, die zweite Null erscheint nicht.

  • scheint Silverlight, ein haben:

http://jesseliberty.com/2009/03/28/toolkit-control-%E2%80%93-timepicker/

aber es ist nicht für WPF.

  • Das WPF Toolkit hat eine Datepicker aber kein Timepicker für sich. Oder gibt es eine Möglichkeit, dem Benutzer Zeit und Datum im WPFToolkit DatePicker einzugeben? Es gibt eine DateTime in SelectedDate zurück, aber ich sehe nicht, wie der Benutzer die Zeit mit diesem Steuerelement auch auswählen kann.

Was ist die beste freie Steuerung WPF-Benutzer geben in HH Zeit lassen: MM: SS-Format?

Antwort

3

Sie können Ihre eigene Rolle ziemlich leicht wie here gezeigt. Und so können Sie genau das bekommen, was Sie wollen.

+0

Dies ist ein ziemlich schönes Beispiel, ich würde einfach Tastatur und Maus eingeben, ohne den Code zu ändern. :-) – wonea

+0

der Zeitwähler ist schrecklich – CRice

5

could't ich eine im Web finden, so dass ich schaffte es von Grund auf neu. Ich verstehe Dependency Properties nicht vollständig, also habe ich diese jetzt weggelassen. Das Steuerelement ist eine 12-Stunden-Zeitauswahlsteuerung. Ich bin neu bei WPF, daher verstehe ich nicht alle neuen Sprachsyntaxen, aber diese Steuerung wird den Trick für mich in dem Projekt, das ich zu Hause erstelle, machen.

Es unterstützt Abbindezeit als Datetime oder Timespan.

Im Folgenden werde ich die XAML und Code-Behind einfügen. Die XAML

<UserControl x:Class="WorkDayManager3.WPF.UserControls.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" 
      mc:Ignorable="d" 
      d:DesignHeight="35" d:DesignWidth="100"> 
    <Border BorderBrush="LightBlue" BorderThickness="1" Margin="1"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition Width="5" /> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <TextBox x:Name="txtHours" BorderThickness="0" MaxLength="2" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Text="1" KeyUp="txt_KeyUp" MouseWheel="txt_MouseWheel" PreviewKeyUp="txt_PreviewKeyUp" /> 
      <TextBlock Text=":" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
      <TextBox x:Name="txtMinutes" BorderThickness="0" MaxLength="2" TextAlignment="Center" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Text="00" KeyUp="txt_KeyUp" MouseWheel="txt_MouseWheel" PreviewKeyUp="txt_PreviewKeyUp" /> 
      <TextBox x:Name="txtAmPm" BorderThickness="0" MaxLength="2" TextAlignment="Center" Grid.Column="3" HorizontalAlignment="Left" VerticalAlignment="Center" PreviewTextInput="txtAmPm_PreviewTextInput" Text="AM" KeyUp="txt_KeyUp" MouseWheel="txt_MouseWheel" Padding="0, 0, 3, 0" /> 
      <Grid Grid.Column="4"> 
       <Grid.RowDefinitions> 
        <RowDefinition /> 
        <RowDefinition /> 
       </Grid.RowDefinitions> 
       <Button x:Name="btnUp" Focusable="False" Click="btnUp_Click"> 
        <TextBlock Text="p" FontFamily="Wingdings 3" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
       </Button> 
       <Button x:Name="btnDown" Grid.Row="1" Focusable="False" Click="btnDown_Click"> 
        <TextBlock Text="q" FontFamily="Wingdings 3" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
       </Button> 
      </Grid> 
     </Grid> 
    </Border> 
</UserControl> 

Code-Behind

using System; 
using System.Linq; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 

namespace WorkDayManager3.WPF.UserControls 
{ 
    /// <summary> 
    /// Interaction logic for TimeControl.xaml 
    /// </summary> 
    public partial class TimeControl : UserControl 
    { 
     public TimeControl() 
     { 
      InitializeComponent(); 
     } 

     #region Properties 

     /// <summary> 
     /// Gets or sets the date time value. 
     /// </summary> 
     /// <value>The date time value.</value> 
     public DateTime? DateTimeValue 
     { 
      get 
      { 
       string hours = this.txtHours.Text; 
       string minutes = this.txtMinutes.Text; 
       string amPm = this.txtAmPm.Text; 
       if (!string.IsNullOrWhiteSpace(hours) 
        && !string.IsNullOrWhiteSpace(minutes) 
        && !string.IsNullOrWhiteSpace(amPm)) 
       { 
        string value = string.Format("{0}:{1} {2}", this.txtHours.Text, this.txtMinutes.Text, this.txtAmPm.Text); 
        DateTime time = DateTime.Parse(value); 
        return time; 
       } 
       else 
       { 
        return null; 
       } 
      } 
      set 
      { 
       DateTime? time = value; 
       if (time.HasValue) 
       { 
        string timeString = time.Value.ToShortTimeString(); 
        //9:54 AM 
        string[] values = timeString.Split(':', ' '); 
        if (values.Length == 3) 
        { 
         this.txtHours.Text = values[0]; 
         this.txtMinutes.Text = values[1]; 
         this.txtAmPm.Text = values[2]; 
        } 
       } 
      } 
     } 

     /// <summary> 
     /// Gets or sets the time span value. 
     /// </summary> 
     /// <value>The time span value.</value> 
     public TimeSpan? TimeSpanValue 
     { 
      get 
      { 
       DateTime? time = this.DateTimeValue; 
       if (time.HasValue) 
       { 
        return new TimeSpan(time.Value.Ticks); 
       } 
       else 
       { 
        return null; 
       } 
      } 
      set 
      { 
       TimeSpan? timeSpan = value; 
       if (timeSpan.HasValue) 
       { 
        this.DateTimeValue = new DateTime(timeSpan.Value.Ticks); 
       } 
      } 
     } 

     #endregion 

     #region Event Subscriptions 

     /// <summary> 
     /// Handles the Click event of the btnDown control. 
     /// </summary> 
     /// <param name="sender">The source of the event.</param> 
     /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param> 
     private void btnDown_Click(object sender, RoutedEventArgs e) 
     { 
      string controlId = this.GetControlWithFocus().Name; 
      if ("txtHours".Equals(controlId)) 
      { 
       this.ChangeHours(false); 
      } 
      else if ("txtMinutes".Equals(controlId)) 
      { 
       this.ChangeMinutes(false); 
      } 
      else if ("txtAmPm".Equals(controlId)) 
      { 
       this.ToggleAmPm(); 
      } 
     } 

     /// <summary> 
     /// Handles the Click event of the btnUp control. 
     /// </summary> 
     /// <param name="sender">The source of the event.</param> 
     /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param> 
     private void btnUp_Click(object sender, RoutedEventArgs e) 
     { 
      string controlId = this.GetControlWithFocus().Name; 
      if ("txtHours".Equals(controlId)) 
      { 
       this.ChangeHours(true); 
      } 
      else if ("txtMinutes".Equals(controlId)) 
      { 
       this.ChangeMinutes(true); 
      } 
      else if ("txtAmPm".Equals(controlId)) 
      { 
       this.ToggleAmPm(); 
      } 
     } 

     /// <summary> 
     /// Handles the PreviewTextInput event of the txtAmPm control. 
     /// </summary> 
     /// <param name="sender">The source of the event.</param> 
     /// <param name="e">The <see cref="System.Windows.Input.TextCompositionEventArgs"/> instance containing the event data.</param> 
     private void txtAmPm_PreviewTextInput(object sender, TextCompositionEventArgs e) 
     { 
      // prevent users to type text 
      e.Handled = true; 
     } 

     /// <summary> 
     /// Handles the KeyUp event of the txt control. 
     /// </summary> 
     /// <param name="sender">The source of the event.</param> 
     /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param> 
     private void txt_KeyUp(object sender, KeyEventArgs e) 
     { 
      // check for up and down keyboard presses 
      if (Key.Up.Equals(e.Key)) 
      { 
       btnUp_Click(this, null); 
      } 
      else if (Key.Down.Equals(e.Key)) 
      { 
       btnDown_Click(this, null); 
      } 
     } 

     /// <summary> 
     /// Handles the MouseWheel event of the txt control. 
     /// </summary> 
     /// <param name="sender">The source of the event.</param> 
     /// <param name="e">The <see cref="System.Windows.Input.MouseWheelEventArgs"/> instance containing the event data.</param> 
     private void txt_MouseWheel(object sender, MouseWheelEventArgs e) 
     { 
      if (e.Delta > 0) 
      { 
       btnUp_Click(this, null); 
      } 
      else 
      { 
       btnDown_Click(this, null); 
      } 
     } 

     /// <summary> 
     /// Handles the PreviewKeyUp event of the txt control. 
     /// </summary> 
     /// <param name="sender">The source of the event.</param> 
     /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param> 
     private void txt_PreviewKeyUp(object sender, KeyEventArgs e) 
     { 
      TextBox textBox = (TextBox)sender; 
      // make sure all characters are number 
      bool allNumbers = textBox.Text.All(Char.IsNumber); 
      if (!allNumbers) 
      { 
       e.Handled = true; 
       return; 
      } 


      // make sure user did not enter values out of range 
      int value; 
      int.TryParse(textBox.Text, out value); 
      if ("txtHours".Equals(textBox.Name) && value > 12) 
      { 
       EnforceLimits(e, textBox); 
      } 
      else if ("txtMinutes".Equals(textBox.Name) && value > 59) 
      { 
       EnforceLimits(e, textBox); 
      } 
     } 

     #endregion 

     #region Methods 

     /// <summary> 
     /// Changes the hours. 
     /// </summary> 
     /// <param name="isUp">if set to <c>true</c> [is up].</param> 
     private void ChangeHours(bool isUp) 
     { 
      int value = Convert.ToInt32(this.txtHours.Text); 
      if (isUp) 
      { 
       value += 1; 
       if (value == 13) 
       { 
        value = 1; 
       } 
      } 
      else 
      { 
       value -= 1; 
       if (value == 0) 
       { 
        value = 12; 
       } 
      } 
      this.txtHours.Text = Convert.ToString(value); 
     } 

     /// <summary> 
     /// Changes the minutes. 
     /// </summary> 
     /// <param name="isUp">if set to <c>true</c> [is up].</param> 
     private void ChangeMinutes(bool isUp) 
     { 
      int value = Convert.ToInt32(this.txtMinutes.Text); 
      if (isUp) 
      { 
       value += 1; 
       if (value == 60) 
       { 
        value = 0; 
       } 
      } 
      else 
      { 
       value -= 1; 
       if (value == -1) 
       { 
        value = 59; 
       } 
      } 

      string textValue = Convert.ToString(value); 
      if (value < 10) 
      { 
       textValue = "0" + Convert.ToString(value); 
      } 
      this.txtMinutes.Text = textValue; 
     } 

     /// <summary> 
     /// Enforces the limits. 
     /// </summary> 
     /// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param> 
     /// <param name="textBox">The text box.</param> 
     /// <param name="enteredValue">The entered value.</param> 
     private static void EnforceLimits(KeyEventArgs e, TextBox textBox) 
     { 
      string enteredValue = GetEnteredValue(e.Key); 
      string text = textBox.Text.Replace(enteredValue, ""); 
      if (string.IsNullOrEmpty(text)) 
      { 
       text = enteredValue; 
      } 
      textBox.Text = text; 
      e.Handled = true; 
     } 

     /// <summary> 
     /// Gets the control with focus. 
     /// </summary> 
     /// <returns></returns> 
     private TextBox GetControlWithFocus() 
     { 
      TextBox txt = new TextBox(); 
      if (this.txtHours.IsFocused) 
      { 
       txt = this.txtHours; 
      } 
      else if (this.txtMinutes.IsFocused) 
      { 
       txt = this.txtMinutes; 
      } 
      else if (this.txtAmPm.IsFocused) 
      { 
       txt = this.txtAmPm; 
      } 
      return txt; 
     } 

     /// <summary> 
     /// Gets the entered value. 
     /// </summary> 
     /// <param name="key">The key.</param> 
     /// <returns></returns> 
     private static string GetEnteredValue(Key key) 
     { 
      string value = string.Empty; 
      switch (key) 
      { 
       case Key.D0: 
       case Key.NumPad0: 
        value = "0"; 
        break; 
       case Key.D1: 
       case Key.NumPad1: 
        value = "1"; 
        break; 
       case Key.D2: 
       case Key.NumPad2: 
        value = "2"; 
        break; 
       case Key.D3: 
       case Key.NumPad3: 
        value = "3"; 
        break; 
       case Key.D4: 
       case Key.NumPad4: 
        value = "4"; 
        break; 
       case Key.D5: 
       case Key.NumPad5: 
        value = "5"; 
        break; 
       case Key.D6: 
       case Key.NumPad6: 
        value = "6"; 
        break; 
       case Key.D7: 
       case Key.NumPad7: 
        value = "7"; 
        break; 
       case Key.D8: 
       case Key.NumPad8: 
        value = "8"; 
        break; 
       case Key.D9: 
       case Key.NumPad9: 
        value = "9"; 
        break; 
      } 
      return value; 
     } 

     /// <summary> 
     /// Toggles the am pm. 
     /// </summary> 
     private void ToggleAmPm() 
     { 
      if ("AM".Equals(this.txtAmPm.Text)) 
      { 
       this.txtAmPm.Text = "PM"; 
      } 
      else 
      { 
       this.txtAmPm.Text = "AM"; 
      } 
     } 

     #endregion 
    } 
} 

, dass die Steuerung ist, fühlen sich frei, Änderungen vorzunehmen, je nach Bedarf. Es ist nicht perfekt, aber es ist besser als andere Steuerelemente i

23

gefunden habe ich mag die Steuerelemente aus dem erweiterten WPF-Toolkit: Link to source code on codeplex

Im Paket, das DateTimeUpDown enthalten ist, die für Ihre Zwecke verwendet werden können. Wenn Sie den Date Teil davon nicht verwenden möchten, können Sie den Format auf "ShortTime" oder welches Format Sie auch haben möchten.

Hoffe, dass hilft.

+1

Ich fand sie sehr nützlich. Vielen Dank! –

+0

Ich muss bereuen ... Ich weiß nicht warum, aber sie verwenden eine DateTime? für den Wert des TimePicker ..., der nicht zu meinem Modell passt. Wahrscheinlich könnte ich Dinge tun, um das zu beheben, aber ich gehe lieber zu einem anderen Steuerelement. –

+1

Sie machen das so, dass das Steuerelement bei der Bindung an eine Datenbanktabellenspalte nicht passt, wenn diese Spalte Nullen enthält, wie dies häufig der Fall ist. Wenn Ihr Modell dieses Szenario nicht berücksichtigt, dann braucht es vielleicht mehr Gedanken. –