UWP — как отформатировать время в TimePicker_TimeChanged И выбрать время без кнопок внутри в TimepickerFlyout

Я разрабатываю приложение UWP (Win10 VS2015). У меня две проблемы.

1- Как я могу получить время в этом формате (16:00 или 9:34 и т. д.) в 12-часовом формате, я могу получить значение без PM/AM с помощью этого TimePicker.Time = sender.Time.ToString(@"hh\:mm"), но Мне нужен фактический формат, как я уже упоминал.

Код 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-часовом формате, т.е. 16:00 в 16:00, но мне нужно в 16:00 или 4:00 (это просто пример) . Если я поставлю .ToString(@"hh\:mm tt");, он выдаст исключение. Как это получить пожалуйста.

2- 2-я проблема заключается в том, что когда мы нажимаем на Timepicker, TimePickerFlyout расширяется, и мы выбираем время, нажимая на часы/минуты, а когда завершаем, то нажимаем на отметку (Tick), чтобы выбрать Time ... но мне нужно удалить эти кнопки («Готово» (_/) и «Отмена» (X)) и выбрать время, выбрав «Час/мин» на всплывающей панели, а не нажатие кнопки, и назначить его строке. Я могу удалить кнопки из стиля TimePickerFlyoutPresenter, но как сделать так, чтобы выделение функционировало как нажатие кнопки.

Смотрите скриншот, в первой части доступны 2 кнопки, и это сработало, но мне нужна вторая часть, как показано справа.

введите здесь описание изображения


person Zia Ur Rahman    schedule 05.05.2016    source источник
comment
Пожалуйста, проверьте обновление для проблемы 2   -  person Archana    schedule 05.05.2016


Ответы (1)


Для первой проблемы 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 Для этого вам нужно реализовать собственный TimerPickerFlyout из PickerFlyoutBase или из Flyout. Это немного сложно, и я не работал над этим. Вы можете просмотреть эту ссылку для этого

Существует простой обходной путь. Как вы упомянули в вопросе, вам нужно отредактировать стиль TimePickerFlyoutPresenter.

Я попытался добавить обработчик событий Tapped в FirstPickerHost,SecondPickerHost,ThirdPickerHost. Но вы не можете добавить обработчики событий в 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>

И вы должны установить datacontext 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, — это программный поиск TimePickerFlyoutPresenter с использованием метода VisualTreeHelper getparaent(). Родитель 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

Вот ссылка на полный проект, который решает все проблемы Исходный код

person Archana    schedule 05.05.2016
comment
Уважаемый, пожалуйста, проверьте эту ошибку onedrive.live.com/ - person Zia Ur Rahman; 05.05.2016
comment
@ZiaUrRahman Добавьте template10 в свой проект. Если не хотите, то реализуйте команду. - person Archana; 06.05.2016
comment
Большой! Template10 удалил ошибку Delegate, но var textblock = FindElementInVisualTree‹TextBlock›(grid); эта строка выдает ошибку (имя FindElementInVisualTree‹› не существует в текущем контексте). см. рис. onedrive.live.com/ - person Zia Ur Rahman; 06.05.2016
comment
В порядке. добавлю этот метод - person Archana; 06.05.2016
comment
Я поделился ссылкой на полный проект, который решает почти все проблемы. Удачного кодирования :) - person Archana; 06.05.2016
comment
Большое вам спасибо, это сработало идеально. Перед вашим текущим обновлением я работал и получил такое решение. строка getTxt = ; foreach (var gr in grid.Children) { if (gr is ContentPresenter) { var cp = (gr as ContentPresenter).Content as DatePickerFlyoutItem; getTxt = cp.PrimaryText; } } И удалили часть FindElementInVisualTree, и просто назначьте getTxt для TimeSpan SelectedTime. Tnx снова - person Zia Ur Rahman; 06.05.2016
comment
Но назначить Selected AM/PM было сложно. Не знаю, как они связаны - person Archana; 06.05.2016
comment
Да, я вижу проблему, ИншаАллах скоро найду решение. - person Zia Ur Rahman; 06.05.2016
comment
Я починил это. Проверьте проект, которым я поделился - person Archana; 06.05.2016
comment
Ок, спасибо, проект скачивается, сейчас проверю. - person Zia Ur Rahman; 06.05.2016
comment
Давайте продолжим это обсуждение в чате. - person Zia Ur Rahman; 06.05.2016
comment
Почему PeriodTextBlock всегда равен нулю, а счетчик всегда равен 0. См. рис. onedrive.live.com/ проект работает нормально, но в моем проекте всегда возвращается 0, а кнопка нулевая. Почему? - person Zia Ur Rahman; 06.05.2016
comment
Вы правильно получаете объект Sender? - person Archana; 06.05.2016
comment
Ой! Хорошо, понял, на самом деле сетка таймера была свернута (вы можете видеть на картинке), а фактическая высота и ширина стали 0, поэтому счетчик был 0, но теперь я сделал его видимым, и это сработало. Спасибо, Арчана (надеюсь, это ваше настоящее имя :)) ... вы проделали потрясающую работу, это действительно отличная работа для пользователя UWP, потому что 2 кнопки внутри средства выбора времени / даты не имеют смысла, оно должно вести себя как средство выбора iOS. control, и ты сделал это сегодня... Твой никнейм LoveToCode тебе очень подходит. Большое вам спасибо... И если возможно, пожалуйста, дайте мне ваш идентификатор скайпа. В ближайшее время я опубликую некоторые другие вопросы, и свяжусь с вами. - person Zia Ur Rahman; 06.05.2016
comment
Спасибо. Это много значит для меня. Вы всегда можете задать вопросы здесь. Более того, я буду активен на этом сайте. И есть много людей, которые готовы вам помочь. - person Archana; 06.05.2016
comment
Да, хорошо, не беспокойтесь... Я буду задавать вопросы здесь. Благодарю. :) - person Zia Ur Rahman; 06.05.2016