mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
Add selected state event to DatePicker
Add selected state event to DatePicker
This commit is contained in:
parent
c186265537
commit
d4fe9e6d91
@ -358,6 +358,15 @@ public class Calendar : TemplatedControl
|
||||
internal DateTime DisplayDateRangeEnd => DisplayDateEnd.GetValueOrDefault(DateTime.MaxValue);
|
||||
internal bool HasFocusInternal { get; set; }
|
||||
|
||||
internal static readonly StyledProperty<bool> IsPointerInMonthViewProperty =
|
||||
AvaloniaProperty.Register<Calendar, bool>(nameof(IsPointerInMonthView), false);
|
||||
|
||||
internal bool IsPointerInMonthView
|
||||
{
|
||||
get => GetValue(IsPointerInMonthViewProperty);
|
||||
set => SetValue(IsPointerInMonthViewProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private bool _displayDateIsChanging;
|
||||
@ -375,7 +384,7 @@ public class Calendar : TemplatedControl
|
||||
HorizontalAlignmentProperty.OverrideDefaultValue<Calendar>(HorizontalAlignment.Left);
|
||||
VerticalAlignmentProperty.OverrideDefaultValue<Calendar>(VerticalAlignment.Top);
|
||||
}
|
||||
|
||||
|
||||
public Calendar()
|
||||
{
|
||||
SetCurrentValue(DisplayDateProperty, DateTime.Today);
|
||||
|
@ -10,6 +10,7 @@ using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.Raw;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
|
||||
@ -204,6 +205,9 @@ internal class CalendarItem : TemplatedControl
|
||||
protected IconButton? _previousButton;
|
||||
protected IconButton? _previousMonthButton;
|
||||
|
||||
// 当鼠标移动到日历单元格外面的时候还原 hover 临时的高亮
|
||||
private IDisposable? _pointerPositionDisposable;
|
||||
|
||||
internal Calendar? Owner { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -1076,6 +1080,41 @@ internal class CalendarItem : TemplatedControl
|
||||
PseudoClasses.Set(CalendarDisabledPC, !isEnabled);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty, GlobalTokenResourceKey.BorderThickness, BindingPriority.Template,
|
||||
new RenderScaleAwareThicknessConfigure(this, thickness => new Thickness(0, 0, 0, thickness.Bottom)));
|
||||
var inputManager = AvaloniaLocator.Current.GetService<IInputManager>()!;
|
||||
_pointerPositionDisposable = inputManager.Process.Subscribe(DetectPointerPosition);
|
||||
}
|
||||
|
||||
private void DetectPointerPosition(RawInputEventArgs args)
|
||||
{
|
||||
if (Owner is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (args is RawPointerEventArgs pointerEventArgs)
|
||||
{
|
||||
if (!IsPointerInMonthView(pointerEventArgs.Position))
|
||||
{
|
||||
Owner.IsPointerInMonthView = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Owner.IsPointerInMonthView = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
_pointerPositionDisposable?.Dispose();
|
||||
}
|
||||
|
||||
protected virtual bool IsPointerInMonthView(Point position)
|
||||
{
|
||||
if (Owner is null)
|
||||
@ -1099,11 +1138,4 @@ internal class CalendarItem : TemplatedControl
|
||||
return new Rect(firstDayPos,
|
||||
new Size(monthView.Bounds.Width, monthViewPos.Y + monthView.Bounds.Height - firstDayPos.Y));
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty, GlobalTokenResourceKey.BorderThickness, BindingPriority.Template,
|
||||
new RenderScaleAwareThicknessConfigure(this, thickness => new Thickness(0, 0, 0, thickness.Bottom)));
|
||||
}
|
||||
}
|
@ -5,12 +5,37 @@ namespace AtomUI.Controls;
|
||||
|
||||
public class DatePicker : InfoPickerInput
|
||||
{
|
||||
|
||||
private DatePickerPresenter? _pickerPresenter;
|
||||
|
||||
protected override Flyout CreatePickerFlyout()
|
||||
{
|
||||
return new DatePickerFlyout();
|
||||
}
|
||||
|
||||
protected override void NotifyPresenterCreated(Control presenter)
|
||||
protected override void NotifyFlyoutPresenterCreated(Control flyoutPresenter)
|
||||
{
|
||||
if (flyoutPresenter is DatePickerFlyoutPresenter datePickerFlyoutPresenter)
|
||||
{
|
||||
datePickerFlyoutPresenter.AttachedToVisualTree += (sender, args) =>
|
||||
{
|
||||
_pickerPresenter = datePickerFlyoutPresenter.DatePickerPresenter;
|
||||
ConfigurePickerPresenter(_pickerPresenter);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigurePickerPresenter(DatePickerPresenter? presenter)
|
||||
{
|
||||
if (presenter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
presenter.ChoosingStatueChanged += (sender, args) =>
|
||||
{
|
||||
_isChoosing = args.IsChoosing;
|
||||
UpdatePseudoClasses();
|
||||
};
|
||||
}
|
||||
}
|
@ -1,6 +1,17 @@
|
||||
namespace AtomUI.Controls;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
public class DatePickerFlyoutPresenter : FlyoutPresenter
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
internal class DatePickerFlyoutPresenter : FlyoutPresenter
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(DatePickerFlyoutPresenter);
|
||||
|
||||
internal DatePickerPresenter? DatePickerPresenter;
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
DatePickerPresenter = e.NameScope.Get<DatePickerPresenter>(DatePickerFlyoutPresenterTheme.DatePickerPresenterPart);
|
||||
}
|
||||
}
|
@ -1,31 +1,177 @@
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Controls.CalendarView;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Layout;
|
||||
using PickerCalendar = AtomUI.Controls.CalendarView.Calendar;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class ChoosingStatusEventArgs : EventArgs
|
||||
{
|
||||
public bool IsChoosing { get; }
|
||||
public ChoosingStatusEventArgs(bool isChoosing)
|
||||
{
|
||||
IsChoosing = isChoosing;
|
||||
}
|
||||
}
|
||||
|
||||
internal class DatePickerPresenter : PickerPresenterBase
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<bool> IsNeedConfirmProperty =
|
||||
AvaloniaProperty.Register<DatePickerPresenter, bool>(nameof(IsNeedConfirm));
|
||||
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowNowProperty =
|
||||
AvaloniaProperty.Register<DatePickerPresenter, bool>(nameof(IsShowNow));
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowTimeProperty =
|
||||
AvaloniaProperty.Register<DatePickerPresenter, bool>(nameof(IsShowTime));
|
||||
|
||||
public static readonly StyledProperty<DateTime?> SelectedDateTimeProperty =
|
||||
AvaloniaProperty.Register<DatePickerPresenter, DateTime?>(nameof(SelectedDateTime));
|
||||
|
||||
public bool IsNeedConfirm
|
||||
{
|
||||
get => GetValue(IsNeedConfirmProperty);
|
||||
set => SetValue(IsNeedConfirmProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowNow
|
||||
{
|
||||
get => GetValue(IsShowNowProperty);
|
||||
set => SetValue(IsShowNowProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowTime
|
||||
{
|
||||
get => GetValue(IsShowTimeProperty);
|
||||
set => SetValue(IsShowTimeProperty, value);
|
||||
}
|
||||
|
||||
public DateTime? SelectedDateTime
|
||||
{
|
||||
get => GetValue(SelectedDateTimeProperty);
|
||||
set => SetValue(SelectedDateTimeProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共事件定义
|
||||
|
||||
/// <summary>
|
||||
/// 当前 Pointer 选中的日期和时间的变化事件
|
||||
/// </summary>
|
||||
public event EventHandler<DateSelectedEventArgs>? HoverDateTimeChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 当前是否处于选择中状态
|
||||
/// </summary>
|
||||
public event EventHandler<ChoosingStatusEventArgs>? ChoosingStatueChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
private Button? _nowButton;
|
||||
private Button? _todayButton;
|
||||
private Button? _confirmButton;
|
||||
private PickerCalendar? _calendarView;
|
||||
private IDisposable? _choosingStateDisposable;
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty, GlobalTokenResourceKey.BorderThickness, BindingPriority.Template,
|
||||
new RenderScaleAwareThicknessConfigure(this, thickness => new Thickness(0, thickness.Top, 0, 0)));
|
||||
if (_calendarView is not null)
|
||||
{
|
||||
_choosingStateDisposable = PickerCalendar.IsPointerInMonthViewProperty.Changed.Subscribe(args =>
|
||||
{
|
||||
ChoosingStatueChanged?.Invoke(this, new ChoosingStatusEventArgs(args.GetNewValue<bool>()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
_choosingStateDisposable = null;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == IsNeedConfirmProperty ||
|
||||
change.Property == IsShowNowProperty ||
|
||||
change.Property == IsShowTimeProperty)
|
||||
{
|
||||
SetupButtonStatus();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_nowButton = e.NameScope.Get<Button>(DatePickerPresenterTheme.NowButtonPart);
|
||||
_todayButton = e.NameScope.Get<Button>(DatePickerPresenterTheme.TodayButtonPart);
|
||||
_confirmButton = e.NameScope.Get<Button>(DatePickerPresenterTheme.ConfirmButtonPart);
|
||||
_calendarView = e.NameScope.Get<PickerCalendar>(DatePickerPresenterTheme.CalendarViewPart);
|
||||
SetupButtonStatus();
|
||||
}
|
||||
|
||||
private void SetupButtonStatus()
|
||||
{
|
||||
if (_nowButton is null ||
|
||||
_todayButton is null ||
|
||||
_confirmButton is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_confirmButton.IsVisible = IsNeedConfirm;
|
||||
|
||||
if (IsShowNow)
|
||||
{
|
||||
if (IsShowTime)
|
||||
{
|
||||
_nowButton.IsVisible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_todayButton.IsVisible = true;
|
||||
}
|
||||
|
||||
if (!IsNeedConfirm)
|
||||
{
|
||||
_nowButton.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
_todayButton.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nowButton.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
_todayButton.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_nowButton.IsVisible = false;
|
||||
_todayButton.IsVisible = false;
|
||||
_nowButton.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
_todayButton.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnConfirmed()
|
||||
{
|
||||
base.OnConfirmed();
|
||||
}
|
||||
|
||||
protected override void OnDismiss()
|
||||
{
|
||||
base.OnDismiss();
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ internal class DatePickerPresenterTheme : BaseControlTheme
|
||||
{
|
||||
public const string MainLayoutPart = "PART_MainLayout";
|
||||
public const string NowButtonPart = "PART_NowButton";
|
||||
public const string TodayButtonPart = "PART_TodayButton";
|
||||
public const string ConfirmButtonPart = "PART_ConfirmButton";
|
||||
public const string ButtonsContainerPart = "PART_ButtonsContainer";
|
||||
public const string ButtonsContainerFramePart = "PART_ButtonsContainerFrame";
|
||||
@ -58,10 +59,12 @@ internal class DatePickerPresenterTheme : BaseControlTheme
|
||||
|
||||
protected virtual Control BuildCalendarView(DatePickerPresenter presenter, INameScope scope)
|
||||
{
|
||||
return new PickerCalendar()
|
||||
var calendarView = new PickerCalendar()
|
||||
{
|
||||
Name = CalendarViewPart
|
||||
};
|
||||
calendarView.RegisterInNameScope(scope);
|
||||
return calendarView;
|
||||
}
|
||||
|
||||
protected virtual Panel BuildButtons(DatePickerPresenter presenter, INameScope scope)
|
||||
@ -81,6 +84,17 @@ internal class DatePickerPresenterTheme : BaseControlTheme
|
||||
LanguageResourceBinder.CreateBinding(nowButton, Button.TextProperty, DatePickerLangResourceKey.Now);
|
||||
nowButton.RegisterInNameScope(scope);
|
||||
buttonsPanel.Children.Add(nowButton);
|
||||
|
||||
var todayButton = new Button
|
||||
{
|
||||
ButtonType = ButtonType.Link,
|
||||
Name = TodayButtonPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Left,
|
||||
SizeType = SizeType.Small
|
||||
};
|
||||
LanguageResourceBinder.CreateBinding(todayButton, Button.TextProperty, DatePickerLangResourceKey.Today);
|
||||
todayButton.RegisterInNameScope(scope);
|
||||
buttonsPanel.Children.Add(todayButton);
|
||||
|
||||
var confirmButton = new Button
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ namespace AtomUI.Controls.Internal;
|
||||
public abstract class InfoPickerInput : TemplatedControl
|
||||
{
|
||||
private const string FlyoutOpenPC = ":flyout-open";
|
||||
private const string ChoosingPC = ":choosing";
|
||||
|
||||
#region 公共属性定义
|
||||
|
||||
@ -171,7 +172,8 @@ public abstract class InfoPickerInput : TemplatedControl
|
||||
protected AddOnDecoratedInnerBox? _pickerInnerBox;
|
||||
protected TextBox? _infoInputBox;
|
||||
|
||||
private bool _isFlyoutOpen;
|
||||
private protected bool _isFlyoutOpen;
|
||||
private protected bool _isChoosing;
|
||||
|
||||
static InfoPickerInput()
|
||||
{
|
||||
@ -305,7 +307,7 @@ public abstract class InfoPickerInput : TemplatedControl
|
||||
};
|
||||
_pickerFlyout.PresenterCreated += (sender, args) =>
|
||||
{
|
||||
NotifyPresenterCreated(args.Presenter);
|
||||
NotifyFlyoutPresenterCreated(args.Presenter);
|
||||
};
|
||||
_flyoutStateHelper.Flyout = _pickerFlyout;
|
||||
}
|
||||
@ -332,7 +334,7 @@ public abstract class InfoPickerInput : TemplatedControl
|
||||
Clear();
|
||||
}
|
||||
|
||||
protected virtual void NotifyPresenterCreated(Control presenter)
|
||||
protected virtual void NotifyFlyoutPresenterCreated(Control flyoutPresenter)
|
||||
{
|
||||
}
|
||||
|
||||
@ -352,6 +354,7 @@ public abstract class InfoPickerInput : TemplatedControl
|
||||
protected virtual void UpdatePseudoClasses()
|
||||
{
|
||||
PseudoClasses.Set(FlyoutOpenPC, _isFlyoutOpen);
|
||||
PseudoClasses.Set(ChoosingPC, _isChoosing);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
|
Loading…
Reference in New Issue
Block a user