Пользовательский элемент управления DateTimePicker .NET MAUI (справка)
Я надеялся получить помощь с пользовательским элементом управления DateTimePicker в .NET MAUI. Я новичок в MAUI и разработке в целом, поэтому заранее извиняюсь, если мой вопрос не ясен.
Я пытаюсь выполнить следующее:
- Пользователь выбирает запись, и появляются средства выбора даты и времени.
- После выбора даты и времени средства выбора исчезают, а метка записи заполняется выбранной датой и временем.
Я пытался использовать несфокусированное событие в средствах выбора, чтобы скрыть их, но когда вы выбираете средство выбора времени (в качестве примера), оно исчезает до того, как время будет полностью выбрано, и метка не обновляется соответствующим образом. Ниже то, что у меня есть до сих пор, любая помощь или предложения очень ценятся!
XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:inputLayout="clr-namespace:Syncfusion.Maui.Core;assembly=Syncfusion.Maui.Core"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
x:Class="TestApplication.View.DateTimePicker">
<VerticalStackLayout Padding="10">
<inputLayout:SfTextInputLayout x:Name="EntryField"
IsHintAlwaysFloated="True"
ContainerType="Outlined"
ContainerBackground="Transparent">
<inputLayout:SfTextInputLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="Entry_Tapped" />
</inputLayout:SfTextInputLayout.GestureRecognizers>
<Entry IsReadOnly="True" x:Name="entry"/>
<inputLayout:SfTextInputLayout.LeadingView>
<ImageButton Source="calendar.png"/>
</inputLayout:SfTextInputLayout.LeadingView>
</inputLayout:SfTextInputLayout>
<HorizontalStackLayout Spacing="10" IsVisible="False" x:Name="picker" HorizontalOptions="Center">
<DatePicker x:Name="datePicker" DateSelected="DatePicker_DateSelected" Format="MM/dd/yyyy" Unfocused="Picker_Unfocused"/>
<TimePicker x:Name="timePicker" Focused="TimePicker_TimeSelected" Unfocused="Picker_Unfocused"/>
</HorizontalStackLayout>
</VerticalStackLayout>
</ContentView>
Код позади:
using System.ComponentModel;
namespace TestApplication.View;
public partial class DateTimePicker : ContentView, INotifyPropertyChanged
{
public DateTimePicker()
{
InitializeComponent();
}
public static readonly BindableProperty DateTimeProperty =
BindableProperty.Create(nameof(DateTime), typeof(DateTime), typeof(DateTimePicker), DateTime.Now, BindingMode.TwoWay);
public event EventHandler DateTimeUpdated;
public event PropertyChangedEventHandler PropertyChanged;
public DateTime DateTime
{
get => (DateTime)GetValue(DateTimeProperty);
set
{
SetValue(DateTimeProperty, value);
OnPropertyChanged("DateTime");
DateTimeUpdated?.Invoke(this, EventArgs.Empty);
}
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
DateTimeUpdated?.Invoke(this, EventArgs.Empty);
}
private void DatePicker_DateSelected(object sender, DateChangedEventArgs e)
{
DateTime = new DateTime(e.NewDate.Year, e.NewDate.Month, e.NewDate.Day, timePicker.Time.Hours, timePicker.Time.Minutes, 0);
entry.Text = DateTime.ToString("MM/dd/yyyy h:mm tt");
DateTimeUpdated?.Invoke(this, EventArgs.Empty);
}
private void TimePicker_TimeSelected(object sender, FocusEventArgs e)
{
DateTime = new DateTime(DateTime.Year, DateTime.Month, DateTime.Day, timePicker.Time.Hours, timePicker.Time.Minutes, 0);
entry.Text = DateTime.ToString("MM/dd/yyyy h:mm tt");
DateTimeUpdated?.Invoke(this, EventArgs.Empty);
}
private void Entry_Tapped(object sender, EventArgs e)
{
picker.IsVisible = !picker.IsVisible;
}
private void Picker_Unfocused(object sender, FocusEventArgs e)
{
picker.IsVisible = false;
}
}
1 ответ
Вы можете попробовать использовать MVVM для достижения:
public class MyVM : INotifyPropertyChanged
{
private DateTime _selectedDate;
private TimeSpan _selectedTime;
public MyVM()
{
_selectedDate = DateTime.Today;
_selectedTime = DateTime.Now.TimeOfDay;
}
public DateTime SelectedDate
{
get { return _selectedDate; }
set {
if (_selectedDate != value)
{
_selectedDate = value;
OnPropertyChanged(nameof(SelectedDate));
OnPropertyChanged(nameof(SelectedDateTime));
OnPropertyChanged(nameof(SelectedDateTimeString));
}
}
}
public TimeSpan SelectedTime
{
get { return _selectedTime; }
set
{
if (_selectedTime != value)
{
_selectedTime = value;
OnPropertyChanged(nameof(SelectedTime));
OnPropertyChanged(nameof(SelectedDateTime));
OnPropertyChanged(nameof(SelectedDateTimeString));
}
}
}
public DateTime SelectedDateTime
{
get { return new DateTime(SelectedDate.Year, SelectedDate.Month, SelectedDate.Day, SelectedTime.Hours, SelectedTime.Minutes, SelectedTime.Seconds); }
}
public string SelectedDateTimeString
{
get { return SelectedDateTime.ToString("MM/dd/yyyy hh:mm tt"); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Xaml:
<StackLayout>
<Entry x:Name="entry"
Text="{Binding SelectedDateTimeString}"
Focused="OnEntryFocused"/>
<Grid x:Name="pickerLayout" IsVisible="false">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<DatePicker Grid.Row="0" Date="{Binding SelectedDate}" />
<TimePicker Grid.Row="1" Time="{Binding SelectedTime}" />
<Button Grid.Row="2" Text="OK" Clicked="OnPickerOKClicked"/>
</Grid>
</StackLayout>
Файл Xamal.cs:
public partial class MyPicker : ContentView
{
MyVM vm = new MyVM();
public MyPicker()
{
InitializeComponent();
BindingContext = vm;
}
private async void OnEntryFocused(object sender, FocusEventArgs e)
{
entry.IsVisible = false;
pickerLayout.IsVisible = true;
await Task.Run(() => WaitForChangedResult());
}
private async void OnPickerOKClicked(object sender,EventArgs e)
{
pickerLayout.IsVisible = false;
entry.IsVisible = true;
OnPropertyChanged(nameof(vm.SelectedDateTimeString));
}
private void WaitForChangedResult() {
while (pickerLayout.IsVisible)
{
Thread.Sleep(100);
}
}
}