2009-12-02 4 views
17

Sto cercando un semplice strumento di controllo orario per WPF.Qual è attualmente il migliore programma di selezione del tempo libero per WPF?

  • io ho trovato trovato questo:

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

ma ha alcuni problemi esempio non è possibile digitare "00" in esso, il secondo zero non verrà visualizzato.

  • Silverlight sembra avere uno:

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

ma è non per WPF.

  • Il toolkit WPF ha un DatePicker ma non un TimePicker di per sé. O c'è un modo per consentire all'utente di inserire ora e data nel DatePicker di WPFToolkit? Lo restituisce un DateTime in SelectedDate ma non vedo come consentire all'utente di scegliere anche l'ora con questo controllo.

Qual è il miglior controllo WPF libero per consentire agli utenti di immettere il tempo in formato HH: SS: MM?

risposta

3

È possibile eseguire facilmente il rollover come mostrato in here. E in questo modo, puoi ottenere esattamente quello che vuoi.

+0

Questo è un bell'esempio, mi basta prendere l'input da tastiera e mouse senza modificare il codice. :-) – wonea

+0

il time picker è terribile – CRice

5

Impossibile trovarne uno sul Web, quindi l'ho creato da zero. Non capisco completamente le proprietà di dipendenza, quindi per ora sono omesso. Il controllo è un controllo di selezione orario di 12 ore. Sono nuovo di WPF quindi non capisco completamente tutte le nuove sintassi del linguaggio, ma questo controllo farà il trucco per me nel progetto che sto creando a casa.

Supporta il tempo di impostazione come DateTime o TimeSpan.

Sotto incollerò XAML e Code-Behind. Il 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 
    } 
} 

Questo è il controllo, si sentono liberi di apportare modifiche in base alle esigenze. Non è perfetto, ma è meglio di altri controlli ho trovato

23

mi piacciono i controlli dalla estesa toolkit WPF: Link to source code on codeplex

Nel pacchetto, il DateTimeUpDown è contenuto che può essere utilizzato per il vostro scopo. Se non si desidera utilizzare la parte Date di esso, è possibile impostare Format su "ShortTime" o qualsiasi altro formato si desideri.

Spero che questo aiuti.

+1

Li ho trovati molto utili. Grazie! –

+0

Devo rimpiangere ... non so perché ma usano un DateTime? per il valore di TimePicker ... che non si adatta al mio modello. Probabilmente potrei fare delle cose per risolverlo ma preferisco passare a un altro controllo. –

+1

Eseguono questa operazione in modo che quando si esegue il binding a una colonna della tabella del database, il controllo non abbia un adattamento quando quella colonna contiene valori null, come spesso accade. Se il tuo modello non considera questo scenario, forse ha bisogno di più pensiero. –