UWP - 如何在 TimepickerFlyout 中格式化 TimePicker_TimeChanged 和 Select 中没有按钮的时间

UWP - How to format time in TimePicker_TimeChanged AND Select Time without Buttons inside in TimepickerFlyout

我正在开发 UWP App (Win10 VS2015)。我有两个问题。

1- 如何以 12 小时格式获取这种格式的时间(下午 4:00 或 9:34 上午等..),我可以获得通过此 TimePicker.Time = sender.Time.ToString(@"hh\:mm") 没有 PM/AM 的值,但我需要我提到的实际格式。

XAML代码

<TimePicker ClockIdentifier="12HourClock" TimeChanged="TimePicker_TimeChanged" Style="{StaticResource TimePickerStyleCustom}"/>

.cs代码

private void TimePicker_TimeChanged(object sender, TimePickerValueChangedEventArgs e)
    {            
        timeTitle.Text = (sender as TimePicker).Time.ToString(@"hh\:mm");
    }

通过上面的代码,我可以获得没有 AM/PM 的值,而且它是 24 小时格式,即 4:00PM 在 16:00 中,但我需要它在 [=46] =] 或 4:00AM(这只是一个例子)。如果我输入 .ToString(@"hh\:mm tt"); 它会抛出异常。请问如何获得。

2- 第二个问题是,当我们点击 Timepicker 时,TimePickerFlyout 展开,我们通过点击 hours/minutes 来 select 时间,当完成时然后单击(勾选)标记到 select 时间...但我需要删除这些按钮(完成 (_/) 和取消 (X))和 select 时间 select在 Flyout 面板中单击 Hour/Min 而不是单击按钮并将其分配给字符串。我可以从 TimePickerFlyoutPresenter 样式中删除按钮,然后如何使选择功能像按钮单击一样。

查看屏幕截图,在第一部分中,2 个按钮可用并且有效,但我需要第二部分,如右侧所示。

第一个问题 TimeSpan 表示时间间隔而不是一天中的时间。您必须将其转换为 DateTime,然后对其进行格式化

 private void TestTimePicker_TimeChanged(object sender, TimePickerValueChangedEventArgs e)
        {
          string Text = (sender as TimePicker).Time.ToString(@"hh\:mm");
            var dateTime = new DateTime((sender as TimePicker).Time.Ticks); // Date part is 01-01-0001
            var formattedTime = dateTime.ToString("h:mm tt", CultureInfo.InvariantCulture);
        }

问题2 为此,您必须从 PickerFlyoutBase 或 Flyout 实现自己的 TimerPickerFlyout。这有点复杂,我还没有研究过。你可以看这个那个

有一个简单的解决方法。正如您在问题中提到的,您必须编辑 TimePickerFlyoutPresenter 样式。

我尝试将 Tapped 事件处理程序添加到 FirstPickerHost、SecondPickerHost,ThirdPickerHost.But 您不能在 app.xaml 中添加事件处理程序。所以我使用了 Behavioral SDK 的交互。如果您的项目中使用了 Template10,则无需下载任何内容,只需在 app.xaml

中添加以下名称空间即可
xmlns:interact="using:Microsoft.Xaml.Interactivity" 
xmlns:interactcore="using:Microsoft.Xaml.Interactions.Core"



 <Style TargetType="TimePickerFlyoutPresenter">
        <Setter Property="Width" Value="242" />
        <Setter Property="MinWidth" Value="242" />
        <Setter Property="MaxHeight" Value="396" />
        <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
        <Setter Property="FontWeight" Value="Normal" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" />
        <Setter Property="AutomationProperties.AutomationId" Value="TimePickerFlyoutPresenter" />
        <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}" />
        <Setter Property="BorderThickness" Value="{ThemeResource DateTimeFlyoutBorderThickness}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TimePickerFlyoutPresenter">
                    <Border x:Name="Background"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        MaxHeight="396">
                        <Grid x:Name="ContentPanel">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*" />
                           </Grid.RowDefinitions>

                            <Grid >
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" x:Name="FirstPickerHostColumn" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" x:Name="SecondPickerHostColumn" />
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" x:Name="ThirdPickerHostColumn" />
                                </Grid.ColumnDefinitions>

                                <Rectangle x:Name="HighlightRect" Fill="{ThemeResource SystemControlHighlightListAccentLowBrush}" Grid.Column="0" Grid.ColumnSpan="5" VerticalAlignment="Center" Height="44"  >

                                </Rectangle>

                                <Border x:Name="FirstPickerHost" Grid.Column="0" >
                                    <interact:Interaction.Behaviors>
                                        <interactcore:EventTriggerBehavior EventName="Tapped">
                                            <interactcore:InvokeCommandAction Command="{Binding ClosePopUp}"/>
                                        </interactcore:EventTriggerBehavior>
                                    </interact:Interaction.Behaviors>
                                </Border>
                                <Rectangle x:Name="FirstPickerSpacing" Fill="{ThemeResource SystemControlForegroundBaseLowBrush}" HorizontalAlignment="Center" Width="2" Grid.Column="1" >

                                </Rectangle>
                                <Border x:Name="SecondPickerHost" Grid.Column="2" >
                                    <interact:Interaction.Behaviors>
                                        <interactcore:EventTriggerBehavior EventName="Tapped">
                                            <interactcore:InvokeCommandAction Command="{Binding ClosePopUp}"/>
                                        </interactcore:EventTriggerBehavior>
                                    </interact:Interaction.Behaviors>
                                </Border>
                                <Rectangle x:Name="SecondPickerSpacing" Fill="{ThemeResource SystemControlForegroundBaseLowBrush}" HorizontalAlignment="Center" Width="2" Grid.Column="3" >

                                </Rectangle>
                                <Border x:Name="ThirdPickerHost" Grid.Column="4" >
                                    <interact:Interaction.Behaviors>
                                        <interactcore:EventTriggerBehavior EventName="Tapped">
                                            <interactcore:InvokeCommandAction Command="{Binding ClosePopUp}"/>
                                        </interactcore:EventTriggerBehavior>
                                    </interact:Interaction.Behaviors>
                                </Border>

                            </Grid>

                            <Grid Grid.Row="1"  Visibility="Collapsed">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <Rectangle Height="2" VerticalAlignment="Top" Fill="{ThemeResource SystemControlForegroundBaseLowBrush}" Grid.ColumnSpan="2" />

                                <Button x:Name="AcceptButton" Grid.Column="0" Content="&#xE8FB;" FontFamily="{ThemeResource SymbolThemeFontFamily}" FontSize="16" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Style="{StaticResource DateTimePickerFlyoutButtonStyle}" Margin="0,2,0,0" />
                                <Button x:Name="DismissButton" Grid.Column="1" Content="&#xE711;" FontFamily="{ThemeResource SymbolThemeFontFamily}" FontSize="16" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Style="{StaticResource DateTimePickerFlyoutButtonStyle}" Margin="0,2,0,0" />
                            </Grid>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

并且您必须将 Timepicker 的数据上下文设置为您的视图模型。

   <TimePicker x:Name="TestTimePicker" Time="{Binding SelectedTime,Mode=TwoWay}" ClockIdentifier="12HourClock" Time="0" TimeChanged="TestTimePicker_TimeChanged" >
     </TimePicker>

    public MainPage()
            {
                this.InitializeComponent();
                DataContext = new TestViewModel();
                TestTimePicker.DataContext = this.DataContext;
            }

    public class TestViewModel:INotifyPropertyChanged
        {
            public DelegateCommand<TappedRoutedEventArgs> ClosePopUp { get; set; }
 TimeSpan selectedTime;
        public TimeSpan SelectedTime
        { get { return selectedTime; }
            set
            {
                if (value != selectedTime)
                {
                    selectedTime = value;
                    OnPropertyChanged("SelectedTime");
                }
            }
        }

            public TestViewModel()
        {

            ClosePopUp = new DelegateCommand<TappedRoutedEventArgs>((args) =>
            {
                if (args.OriginalSource is Grid)
                {
                    Grid grid = args.OriginalSource as Grid;
                    if (grid != null)
                    {
                       var fly = FlyoutBase.GetAttachedFlyout(grid);
                        var flyoutpresenter = FindParent<TimePickerFlyoutPresenter>(grid);
                        if (flyoutpresenter != null)
                            (flyoutpresenter.Parent as Popup).IsOpen = false;
                       var firstPicker= FindParent(grid,"FirstPickerHost");
                        var secondPicker = FindParent(grid, "SecondPickerHost");
                        var thirdPicker = FindParent(grid, "ThirdPickerHost");
                        var textblock = FindElementInVisualTree<TextBlock>(grid);
                        if (firstPicker != null)
                        {
                            SelectedTime = new TimeSpan(int.Parse(textblock.Text), SelectedTime.Minutes, SelectedTime.Seconds);

                        }
                         if(secondPicker!=null)
                        {
                            SelectedTime = new TimeSpan(SelectedTime.Hours, int.Parse(textblock.Text), SelectedTime.Seconds);
                        }
                        if (thirdPicker != null)
                        {
                          // AM/PM
                        }

                    }
                }
                else if(args.OriginalSource is TextBlock)
                {
                    TextBlock textblock = args.OriginalSource as TextBlock;
                    if (textblock != null)
                    {
                        var fly = FlyoutBase.GetAttachedFlyout(textblock);
                        var flyoutpresenter = FindParent<TimePickerFlyoutPresenter>(textblock);
                        if (flyoutpresenter != null)
                            (flyoutpresenter.Parent as Popup).IsOpen = false;
                        var firstPicker = FindParent(textblock, "FirstPickerHost");
                        var secondPicker = FindParent(textblock, "SecondPickerHost");
                        var thirdPicker = FindParent(textblock, "ThirdPickerHost");

                        if (firstPicker != null)
                        {
                            SelectedTime = new TimeSpan(int.Parse(textblock.Text), SelectedTime.Minutes, SelectedTime.Seconds);

                        }
                        if (secondPicker != null)
                        {
                            SelectedTime = new TimeSpan(SelectedTime.Hours, int.Parse(textblock.Text), SelectedTime.Seconds);
                        }
                        if (thirdPicker != null)
                        {
                           //  AM/PM
                        }
                    }
                }
                else
                {

                }
            });

        }

        public event PropertyChangedEventHandler PropertyChanged;
        void OnPropertyChanged(string propertyName)
        {
            // the new Null-conditional Operators are thread-safe:
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private T FindParent<T>(DependencyObject child) where T : DependencyObject
        {
            var parent = VisualTreeHelper.GetParent(child);
            if (parent != null && parent is T)
                return (T)parent;
            else if (parent == null)
                return null;
            else
            {
                var result = FindParent<T>(parent);
                if (result != null)
                    return result;

            }
            return null;
        }
        private DependencyObject FindParent(DependencyObject child,string parentName) 
        {
            var parent = VisualTreeHelper.GetParent(child);
            if (parent != null && (parent as FrameworkElement).Name.Equals(parentName))
                return parent;
            else if (parent == null)
                return null;
            else
            {
                var result = FindParent(parent,parentName);
                if (result != null)
                    return result;

            }
            return null;
        }
       private T FindElementInVisualTree<T>(DependencyObject parentElement) where T : DependencyObject
    {
        var count = VisualTreeHelper.GetChildrenCount(parentElement);
        if (count == 0) return null;

        for (int i = 0; i < count; i++)
        {
            var child = VisualTreeHelper.GetChild(parentElement, i);
            if (child != null && child is T)
                return (T)child;
            else
            {
                var result = FindElementInVisualTree<T>(child);
                if (result != null)
                    return result;
            }
        }
        return null;
    }
    }

我在上面的 ClosePopUp 命令中所做的是使用 VisualTreeHelper getparaent() 方法以编程方式查找 TimePickerFlyoutPresenter TimePickerFlyoutPresenter 父项是 PopUp,实际上是您的 TimePickerFlyout。将弹出窗口的 IsOpen 设置为 false

// Updated the code to reflect selected hour and minute in timepicker. One issue left is update the selected AM or PM. I ll update if i get the solution

这是一个 link 可以解决所有问题的完成项目 Source Code