TimeSpanPicker xaml

时间:2014-10-18 12:14:56

标签: c# xaml windows-8 windows-store-apps windows-8.1

我的Windows 8.1(Windows应用商店)应用需要 TimeSpanPicker 控件。我无法在Windows 8工具箱中找到它。如果控件已经可用,请与控件共享任何链接,或者帮助我从头开始构建它。

我已经在线搜索了解决方案,但TimeSpanPicker控件仅适用于Windows Phone而不适用于Windows 8。

如何实现循环控制UI来实现我自己的TimeSpanPicker?

1 个答案:

答案 0 :(得分:0)

这可能是你的幸运日。我刚刚为时间码创建了一个微调器,我使用了timepan作为它的值。 这有点粗糙,但它完成了工作。无论如何,它可能会给你如何建立自己的想法。

注意这是作为自定义控件构建的。我想用户控件也可以工作。

XAML:

 <Style TargetType="{x:Type local:TimeCodeUpDown}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:TimeCodeUpDown}">

                <Grid HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                      VerticalAlignment="{TemplateBinding VerticalAlignment}"
                      SnapsToDevicePixels="True"
                      >
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            HorizontalAlignment="Left"
                            Padding="1"
                            >
                        <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                            <TextBox x:Name="HoursText"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Width="Auto"
                                     Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                            Path=Hours, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="1"/>
                            <TextBox x:Name="HoursSeparator"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Text=":"/>
                            <TextBox x:Name="MinutesText"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Width="Auto"
                                     Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                            Path=Minutes, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="2"/>
                            <TextBox x:Name="MinutesSeparator"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Text=":"/>
                            <TextBox x:Name="SecondsText"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Width="Auto"
                                     Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                            Path=Seconds, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="3"/>
                            <TextBox x:Name="SecondsSeparator"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Text=":"/>
                            <TextBox x:Name="FramesText"
                                     BorderThickness="0"
                                     VerticalAlignment="Center"
                                     Width="Auto"
                                     Text="{Binding RelativeSource={RelativeSource TemplatedParent}, 
                                            Path=Frames, StringFormat={}{0:D2}, Mode=TwoWay}" TabIndex="4"/>

                            <Grid x:Name="ButtonGrid"
                                  Margin="3,0,0,0"
                                  Width="10">
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <Button x:Name="UpButton" Grid.Row="0" 
                                        BorderThickness="0.5" Margin="0,0,0,0.5" 
                                        Background="Transparent">
                                        <Path Stroke="Transparent" Fill="Black"  Data="M 1 3.5 L 2.5 1 L 4 3.5 Z"/>
                                </Button>
                                <Button x:Name="DownButton" 
                                        Grid.Row="1" 
                                        BorderThickness="0.5" Margin="0,0.5,0,0" Background="Transparent">
                                        <Path Stroke="Transparent" Fill="Black"  Data="M 1 1 L 2.5 4 L 4 1 Z"/>
                                </Button>

                            </Grid>
                        </StackPanel>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

CODE:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 Stv.AutoCatch.Desktop.Client.Infrastructure.Controls
{
    /// <summary>
    /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
    ///
    /// Step 1a) Using this custom control in a XAML file that exists in the current project.
    /// Add this XmlNamespace attribute to the root element of the markup file where it is 
    /// to be used:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Stv.AutoCatch.Desktop.Client.Infrastructure.Controls"
    ///
    ///
    /// Step 1b) Using this custom control in a XAML file that exists in a different project.
    /// Add this XmlNamespace attribute to the root element of the markup file where it is 
    /// to be used:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Stv.AutoCatch.Desktop.Client.Infrastructure.Controls;assembly=Stv.AutoCatch.Desktop.Client.Infrastructure.Controls"
    ///
    /// You will also need to add a project reference from the project where the XAML file lives
    /// to this project and Rebuild to avoid compilation errors:
    ///
    ///     Right click on the target project in the Solution Explorer and
    ///     "Add Reference"->"Projects"->[Browse to and select this project]
    ///
    ///
    /// Step 2)
    /// Go ahead and use your control in the XAML file.
    ///
    ///     <MyNamespace:TimeCodeUpDown/>
    ///
    /// </summary>
    public class TimeCodeUpDown : Control
    {
        TextBox _lastFocusedTextBox;

        internal TimeSpan InternalTime
        {
            get { return _internalTime; }
        }
        TimeSpan _internalTime = TimeSpan.Zero;

        static TimeCodeUpDown()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TimeCodeUpDown), new FrameworkPropertyMetadata(typeof(TimeCodeUpDown)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            Button upButton = (Button)base.GetTemplateChild("UpButton");
            Button downButton = (Button)base.GetTemplateChild("DownButton");

            upButton.Click += upButton_Click;
            downButton.Click += downButton_Click;

            TextBox hoursText = (TextBox)base.GetTemplateChild("HoursText");
            hoursText.GotFocus += _hoursText_GotFocus;

            TextBox minutesText = (TextBox)base.GetTemplateChild("MinutesText");
            minutesText.GotFocus += _minutesText_GotFocus;

            TextBox secondsText = (TextBox)base.GetTemplateChild("SecondsText");
            secondsText.GotFocus += _secondsText_GotFocus;

            TextBox framesText = (TextBox)base.GetTemplateChild("FramesText");
            framesText.GotFocus += _framesText_GotFocus;
        }

        void _framesText_GotFocus(object sender, RoutedEventArgs e)
        {
            _lastFocusedTextBox = (TextBox)sender;
        }

        void _secondsText_GotFocus(object sender, RoutedEventArgs e)
        {
            _lastFocusedTextBox = (TextBox)sender;
        }

        void _minutesText_GotFocus(object sender, RoutedEventArgs e)
        {
            _lastFocusedTextBox = (TextBox)sender;
        }

        void _hoursText_GotFocus(object sender, RoutedEventArgs e)
        {
            _lastFocusedTextBox = (TextBox)sender;
        }

        void downButton_Click(object sender, RoutedEventArgs e)
        {
            if (_lastFocusedTextBox != null)
            {
                if (_lastFocusedTextBox.Name.Equals("HoursText"))
                {
                    if (this.Hours > 0)
                        this.Hours--;
                    else if (this.Hours == 0)
                        this.Hours = 23;

                }
                if (_lastFocusedTextBox.Name.Equals("MinutesText"))
                {
                    if (this.Minutes > 0)
                        this.Minutes--;
                    else if (this.Minutes == 0)
                        this.Minutes = 59;
                }
                if (_lastFocusedTextBox.Name.Equals("SecondsText"))
                {
                    if (this.Seconds > 0)
                        this.Seconds--;
                    else if (this.Seconds == 0)
                        this.Seconds = 59;
                }
                if (_lastFocusedTextBox.Name.Equals("FramesText"))
                {
                    if (this.Frames > 0)
                        this.Frames--;
                    else if (this.Frames == 0)
                        this.Frames = 24;
                }
            }
        }

        void upButton_Click(object sender, RoutedEventArgs e)
        {
            if (_lastFocusedTextBox != null)
            {

                if (_lastFocusedTextBox.Name.Equals("HoursText"))
                {
                    if (this.Hours < 23)
                        this.Hours++;
                    else if (this.Hours == 23)
                        this.Hours = 0;

                }
                if (_lastFocusedTextBox.Name.Equals("MinutesText"))
                {
                    if (this.Minutes < 59)
                        this.Minutes++;
                    else if (this.Minutes == 59)
                        this.Minutes = 0;
                }
                if (_lastFocusedTextBox.Name.Equals("SecondsText"))
                {
                    if (this.Seconds < 59)
                        this.Seconds++;
                    else if (this.Seconds == 59)
                        this.Seconds = 0;
                }
                if (_lastFocusedTextBox.Name.Equals("FramesText"))
                {
                    if (this.Frames < 24)
                        this.Frames++;
                    else if (this.Frames == 24)
                        this.Frames = 0;
                }
            }
        }

        public TimeSpan TimeValue
        {
            get { return (TimeSpan)GetValue(TimeValueProperty); }
            set { SetValue(TimeValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TimeValue.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TimeValueProperty =
            DependencyProperty.Register("TimeValue", typeof(TimeSpan), typeof(TimeCodeUpDown), new PropertyMetadata(TimeSpan.Zero, new PropertyChangedCallback(OnTimeValueChanged)));

        private static void OnTimeValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = (TimeCodeUpDown)d;

            TimeSpan newValue = (TimeSpan)e.NewValue;
            if (newValue < TimeSpan.Zero || newValue >= TimeSpan.FromDays(1))  // ensure TimeSpan is less than 1 day and not negative.
                newValue = new TimeSpan(0, newValue.Hours, newValue.Minutes, newValue.Seconds, newValue.Milliseconds);

            if(!instance._internalTime.Equals(newValue))
            {
                // we are being changed from outside the control.
                var absoluteTime = Convert.ToInt64(25 * newValue.TotalSeconds);


                instance.Hours = Convert.ToInt32((absoluteTime / 90000) % 24);
                instance.Minutes = Convert.ToInt32((absoluteTime - (90000 * instance.Hours)) / 1500);
                instance.Seconds = Convert.ToInt32(((absoluteTime - (1500 * instance.Minutes) - (90000 * instance.Hours)) / 25));
                instance.Frames = Convert.ToInt32(absoluteTime - (25 * instance.Seconds) - (1500 * instance.Minutes) - (90000 * instance.Hours));
            }
        }


        //internal ICommand



        public int Hours
        {
            get { return (int)GetValue(HoursProperty); }
            set { SetValue(HoursProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Hours.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HoursProperty =
            DependencyProperty.Register("Hours", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnHoursChanged)));

        private static void OnHoursChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = (TimeCodeUpDown)d;
            TimeSpan newTime =
                new TimeSpan(0, (int)e.NewValue, instance.TimeValue.Minutes, instance.TimeValue.Seconds, instance.TimeValue.Milliseconds);
            instance._internalTime = newTime;
            instance.TimeValue = newTime;
        }



        public int Minutes
        {
            get { return (int)GetValue(MinutesProperty); }
            set { SetValue(MinutesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Minutes.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinutesProperty =
            DependencyProperty.Register("Minutes", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnMinutesChanged)));

        private static void OnMinutesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = (TimeCodeUpDown)d;
            TimeSpan newTime =
                new TimeSpan(0, instance.TimeValue.Hours, (int)e.NewValue, instance.TimeValue.Seconds, instance.TimeValue.Milliseconds);
            instance._internalTime = newTime;
            instance.TimeValue = newTime;
        }




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

        // Using a DependencyProperty as the backing store for Seconds.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SecondsProperty =
            DependencyProperty.Register("Seconds", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnSecondsChanged)));

        private static void OnSecondsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = (TimeCodeUpDown)d;
            TimeSpan newTime =
                new TimeSpan(0, instance.TimeValue.Hours, instance.TimeValue.Minutes, (int)e.NewValue, instance.TimeValue.Milliseconds);
            instance._internalTime = newTime;
            instance.TimeValue = newTime;
        }

        public int Frames
        {
            get { return (int)GetValue(FramesProperty); }
            set { SetValue(FramesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Frames.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FramesProperty =
            DependencyProperty.Register("Frames", typeof(int), typeof(TimeCodeUpDown), new PropertyMetadata(0, new PropertyChangedCallback(OnFramesChanged)));

        private static void OnFramesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = (TimeCodeUpDown)d;
            TimeSpan newTime =
                new TimeSpan(0, instance.TimeValue.Hours, instance.TimeValue.Minutes, instance.TimeValue.Seconds, (int)e.NewValue * 40);
            instance._internalTime = newTime;
            instance.TimeValue = newTime;
        }


    }
}