web-dev-qa-db-fra.com

Existe-t-il un contrôle TimePicker dans WPF (.NET 4)?

Existe-t-il un contrôle TimePicker dans WPF (.NET 4)?

J'espérais que le contrôle DatePicker avait la capacité d'afficher une donnée ou une heure ou les deux, mais cela ne semble pas. L'un ou l'autre d'entre eux conviendrait pour moi:

Wednesday, February 8th, 2012 2:27 pm

-ou:

2:27 pm

(que j'utiliserais en conjonction avec un DatePicker)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~

Mise à jour (après avoir essayé d'installer les contrôles WPF étendus):

Voilà pour cela/ce n'est pas aussi facile qu'il y paraît/devrait l'être.

Lorsque j'ai essayé de télécharger la boîte à outils WPF étendue à partir de http://wpftoolkit.codeplex.com/releases/view/71499 je suis entré dans ma boîte de dialogue de téléchargement:

http://download.codeplex.com/site/pagenotfound?ReferenceId=f1704e1d-3152-4ecf-b2bb-ace62735bcbc

(notez la partie "page non trouvée" - rien téléchargé).

... alors j'ai procédé au plan B et j'ai essayé de télécharger/installer Nuget, afin que je puisse obtenir le WPF Toolkit étendu de cette façon (via Tools | Extension Manager | Online Gallery | Updates (1) | NeGet Package Manager | Download).

J'ai d'abord dû décocher la case "Protégez-moi contre le code potentiellement malveillant" (ou quelque chose dans ce sens - je l'avais essayé (deux fois!) Sans décocher cette case, et il s'est écrasé les deux fois); puis (après avoir décoché la case), j'ai vu dans la boîte de dialogue d'installation, "Cette extension contient une signature numérique avec un certificat non valide."

J'ai quand même continué et j'ai finalement installé Nuget.

Donc, après avoir redémarré Visual Studio 2010, je suis allé dans Outils | Gestionnaire de packages de bibliothèque | La console du gestionnaire de packages, mais a été accueillie avec l'erreur: la console du gestionnaire de packages requiert le runtime PowerShell 2.0, qui n'est pas détecté sur cette machine. Veuillez installer PowerShell 2.0 à partir de http://support.Microsoft.com/kb/968929 et redémarrer Visual Studio.rt Visual Studio. "

Puis, lorsque je suis allé installer cette mise à jour (WindowsXP-KB968930-x86-ENG.exe), j'ai reçu: "L'application update/update.exe ne peut pas être exécutée en mode Win32." et il a échoué.

Achhh !!! C'est comme un lundi!

36
B. Clay Shannon

WPF 4.0 ne fournit pas un DateTimePicker prêt à l'emploi.

Mise à jour J'utilise le Extended WPF Toolkit http : //wpftoolkit.codeplex.com/ dans un projet récent, il inclut un Nice DateTimePicker Control - http://wpftoolkit.codeplex.com/wikipage?title=DateTimePicker&referringTitle=Home .

Désolé pour cette inexactitude.

35
d_schnell

Découvrez la boîte à outils WPF étendue DateTimeUpDown sur Codeplex ( ou connexe SO post).

6
SliverNinja - MSFT

WPF n'en fait pas officiellement, mais vous pouvez vérifier ce que ce gars a fait:
Sélecteur de temps WPF

Ou vous pouvez créer le votre

1
MyKuLLSKI

Ma solution pour un contrôle simple du temps

TimeControl.xaml

<UserControl x:Class="Infra.UICommon.Controls.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" 
             xmlns:local="clr-namespace:Infra.UICommon.Controls"
             mc:Ignorable="d" 
             Height="Auto" Width="Auto" x:Name="UserControl" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid x:Name="LayoutRoot" Width="Auto" Height="Auto" Background="White">
        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="0.2*"/>

            <ColumnDefinition Width="0.05*"/>

            <ColumnDefinition Width="0.2*"/>

            <ColumnDefinition Width="0.05*"/>

            <ColumnDefinition Width="0.2*"/>

            <ColumnDefinition Width="0.05*"/>

            <ColumnDefinition Width="0.2*"/>

        </Grid.ColumnDefinitions>

        <!-- Hours -->
        <Grid x:Name="hours" Focusable="True" MouseWheel="OnMouseWheel" >
            <TextBox x:Name="hh" TextWrapping="Wrap" Text="{Binding Path=Hours, ElementName=UserControl, Mode=Default}" 
                     PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput"  DataObject.Pasting="OnTextPasting" 
                     TextAlignment="Center" VerticalAlignment="Center"  BorderThickness="0"/>
        </Grid>

        <!-- Separator ':' -->
        <Grid  Grid.Column="1">
            <TextBox IsReadOnly="True" x:Name="sep1" TextWrapping="Wrap" VerticalAlignment="Center" Text=":" TextAlignment="Center"  BorderThickness="0"/>
        </Grid>

        <!-- Minutes -->
        <Grid  Grid.Column="2" x:Name="minutes" Focusable="True" MouseWheel="OnMouseWheel">
            <TextBox  x:Name="mm"  TextWrapping="Wrap" Text="{Binding Path=Minutes, ElementName=UserControl, Mode=Default}" 
                      PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput"  DataObject.Pasting="OnTextPasting" 
                      TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0" />
        </Grid>

        <!-- Separator ':' -->
        <Grid  Grid.Column="3">
            <TextBox IsReadOnly="True" x:Name="sep2"  TextWrapping="Wrap" VerticalAlignment="Center" Text=":" TextAlignment="Center"  BorderThickness="0"/>
        </Grid>

        <!-- Seconds -->
        <Grid  Grid.Column="4" Name="seconds" Focusable="True" MouseWheel="OnMouseWheel">
            <TextBox x:Name="ss"  TextWrapping="Wrap" Text="{Binding Path=Seconds, ElementName=UserControl, Mode=Default}" 
                     PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput"  DataObject.Pasting="OnTextPasting" 
                     TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0" />
        </Grid>

        <!-- Separator ':' -->
        <Grid  Grid.Column="5">
            <TextBox IsReadOnly="True" x:Name="sep3"  TextWrapping="Wrap" VerticalAlignment="Center"  Text=":" TextAlignment="Center"  BorderThickness="0"/>
        </Grid>

        <!-- Milliseconds -->
        <Grid  Grid.Column="6" Name="miliseconds" Focusable="True" MouseWheel="OnMouseWheel">
            <TextBox x:Name="ff"  TextWrapping="Wrap" Text="{Binding Path=Milliseconds, ElementName=UserControl, Mode=Default}"
                     PreviewKeyDown="OnKeyDown" PreviewTextInput="OnPreviewTextInput"  DataObject.Pasting="OnTextPasting" 
                     TextAlignment="Center" VerticalAlignment="Center" BorderThickness="0" />
        </Grid>

    </Grid>

</UserControl>

TimeControl.xaml.cs (code derrière)

namespace Infra.UICommon.Controls
{
    /// <summary>
    /// Interaction logic for TimeControl.xaml
    /// </summary>
    public partial class TimeControl : UserControl
    {
        public TimeControl()
        {
            InitializeComponent();
        }

        private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            TimeControl control = obj as TimeControl;
            var newTime = (TimeSpan)e.NewValue;

            control.Hours        = newTime.Hours;
            control.Minutes      = newTime.Minutes;
            control.Seconds      = newTime.Seconds;
            control.Milliseconds = newTime.Milliseconds;
        }


        private static void OnTimeChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            TimeControl control = obj as TimeControl;
            control.Value = new TimeSpan(0, control.Hours, control.Minutes, control.Seconds, control.Milliseconds);
        }

        public TimeSpan Value
        {
            get { return (TimeSpan)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
        public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value", typeof(TimeSpan), typeof(TimeControl),
        new FrameworkPropertyMetadata(DateTime.Now.TimeOfDay, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnValueChanged)));



        public int Hours
        {
            get { return (int)GetValue(HoursProperty); }
            set { SetValue(HoursProperty, value); }
        }
        public static readonly DependencyProperty HoursProperty =
        DependencyProperty.Register("Hours", typeof(int), typeof(TimeControl),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));

        public int Minutes
        {
            get { return (int)GetValue(MinutesProperty); }
            set { SetValue(MinutesProperty, value); }
        }
        public static readonly DependencyProperty MinutesProperty =
        DependencyProperty.Register("Minutes", typeof(int), typeof(TimeControl),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));

        public int Seconds
        {
            get { return (int)GetValue(SecondsProperty); }
            set { SetValue(SecondsProperty, value); }
        }

        public static readonly DependencyProperty SecondsProperty =
        DependencyProperty.Register("Seconds", typeof(int), typeof(TimeControl),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));


        public int Milliseconds
        {
            get { return (int)GetValue(MillisecondsProperty); }
            set { SetValue(MillisecondsProperty, value); }
        }

        public static readonly DependencyProperty MillisecondsProperty =
        DependencyProperty.Register("Milliseconds", typeof(int), typeof(TimeControl),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnTimeChanged)));


        private Tuple<int, int> GetMaxAndCurentValues(String name)
        {
            int maxValue = 0;
            int currValue = 0;

            switch (name)
            {
                case "ff":
                    maxValue = 1000;
                    currValue = Milliseconds; 
                    break;

                case "ss":
                    maxValue = 60;
                    currValue = Seconds;
                    break;

                case "mm":
                    maxValue = 60;
                    currValue = Minutes;
                    break;

                case "hh":
                    maxValue = 24;
                    currValue = Hours;
                    break;
            }

            return new Tuple<int, int>(maxValue, currValue);
        }

        private void UpdateTimeValue(String name, int delta)
        {
            var values = GetMaxAndCurentValues(name);
            int maxValue = values.Item1;
            int currValue = values.Item2;

            // Set new value
            int newValue = currValue + delta;

            if (newValue == maxValue)
            {
                newValue = 0;
            }
            else if (newValue < 0)
            {
                newValue += maxValue;
            }


            switch (name)
            {
                case "ff":
                    Milliseconds = newValue;

                    break;

                case "ss":
                    Seconds = newValue;
                    break;

                case "mm":
                    Minutes = newValue;
                    break;

                case "hh":
                    Hours = newValue;
                    break;
            }
        }

        private void OnKeyDown(object sender, KeyEventArgs args)
        {
            try
            {
                int delta = 0;
                String name = ((TextBox)sender).Name;

                if (args.Key == Key.Up) { delta = 1; }
                else if (args.Key == Key.Down) { delta = -1; }

                UpdateTimeValue(name, delta);
            }
            catch { }
        }

        private void OnMouseWheel(object sender, MouseWheelEventArgs e)
        {
            try
            {
                var g = (Grid)(sender);
                var value = g.Children.OfType<TextBox>().FirstOrDefault();

                UpdateTimeValue(value.Name, e.Delta / Math.Abs(e.Delta));
            }
            catch { }

        }

        private Boolean IsTextAllowed(String name, String text)
        {
            try
            {
                foreach (Char c in text.ToCharArray())
                {
                    if (Char.IsDigit(c) || Char.IsControl(c)) continue;
                    else return false;
                }

                var values = GetMaxAndCurentValues(name);
                int maxValue = values.Item1;

                int newValue = Convert.ToInt32(text);

                if (newValue < 0 || newValue >= (Int32)maxValue)
                {
                    return false;
                }

            } catch
            {
                return false;
            }


            return true;
        }

        // Use the OnPreviewTextInput to respond to key presses 
        private void OnPreviewTextInput(Object sender, TextCompositionEventArgs e)
        {
            try
            {
                var tb = (TextBox)sender;


                e.Handled = !IsTextAllowed(tb.Name, tb.Text + e.Text);
            }
            catch { }
        }

        // Use the DataObject.Pasting Handler  
        private void OnTextPasting(object sender, DataObjectPastingEventArgs e)
        {
            try
            {
                String name = ((TextBox)sender).Name;

                if (e.DataObject.GetDataPresent(typeof(String)))
                {
                    String text = (String)e.DataObject.GetData(typeof(String));
                    if (!IsTextAllowed(name, text)) e.CancelCommand();
                }
                else e.CancelCommand();
            }
            catch { }
        }

    }
}

Usage:

<ctrl:TimeControl Value="{Binding StartTime, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="startTime"/>

Où 'ctrl' est l'espace de noms où se trouve le TimeControl et 'StartTime' est une propriété du type 'TimeSpan'.

xmlns:ctrl="clr-namespace:Infra.UICommon.Controls;Assembly=Infra.UICommon"

J'espère que cela t'aides)

p.s. La seule chose qui n'est pas gérée ici est les touches "retour arrière" et "supprimer".

0
Yuri Dosovitsky