|
@@ -1,7 +1,6 @@
|
|
|
using Avalonia.Controls.Metadata;
|
|
|
using Avalonia.Controls.Primitives;
|
|
|
using Avalonia.Controls.Shapes;
|
|
|
-using Avalonia.Controls.Templates;
|
|
|
using Avalonia.Data;
|
|
|
using Avalonia.Interactivity;
|
|
|
using Avalonia.Layout;
|
|
@@ -29,65 +28,56 @@ namespace Avalonia.Controls
|
|
|
/// <summary>
|
|
|
/// Define the <see cref="DayFormat"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, string> DayFormatProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, string>(nameof(DayFormat),
|
|
|
- x => x.DayFormat, (x, v) => x.DayFormat = v);
|
|
|
+ public static readonly StyledProperty<string> DayFormatProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, string>(nameof(DayFormat), "%d");
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="DayVisible"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, bool> DayVisibleProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, bool>(nameof(DayVisible),
|
|
|
- x => x.DayVisible, (x, v) => x.DayVisible = v);
|
|
|
+ public static readonly StyledProperty<bool> DayVisibleProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, bool>(nameof(DayVisible), true);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="MaxYear"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, DateTimeOffset> MaxYearProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, DateTimeOffset>(nameof(MaxYear),
|
|
|
- x => x.MaxYear, (x, v) => x.MaxYear = v);
|
|
|
+ public static readonly StyledProperty<DateTimeOffset> MaxYearProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, DateTimeOffset>(nameof(MaxYear), DateTimeOffset.MaxValue, coerce: CoerceMaxYear);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="MinYear"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, DateTimeOffset> MinYearProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, DateTimeOffset>(nameof(MinYear),
|
|
|
- x => x.MinYear, (x, v) => x.MinYear = v);
|
|
|
+ public static readonly StyledProperty<DateTimeOffset> MinYearProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, DateTimeOffset>(nameof(MinYear), DateTimeOffset.MinValue, coerce: CoerceMinYear);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="MonthFormat"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, string> MonthFormatProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, string>(nameof(MonthFormat),
|
|
|
- x => x.MonthFormat, (x, v) => x.MonthFormat = v);
|
|
|
+ public static readonly StyledProperty<string> MonthFormatProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, string>(nameof(MonthFormat), "MMMM");
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="MonthVisible"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, bool> MonthVisibleProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, bool>(nameof(MonthVisible),
|
|
|
- x => x.MonthVisible, (x, v) => x.MonthVisible = v);
|
|
|
+ public static readonly StyledProperty<bool> MonthVisibleProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, bool>(nameof(MonthVisible), true);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="YearFormat"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, string> YearFormatProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, string>(nameof(YearFormat),
|
|
|
- x => x.YearFormat, (x, v) => x.YearFormat = v);
|
|
|
+ public static readonly StyledProperty<string> YearFormatProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, string>(nameof(YearFormat), "yyyy");
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="YearVisible"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, bool> YearVisibleProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, bool>(nameof(YearVisible),
|
|
|
- x => x.YearVisible, (x, v) => x.YearVisible = v);
|
|
|
+ public static readonly StyledProperty<bool> YearVisibleProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, bool>(nameof(YearVisible), true);
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="SelectedDate"/> Property
|
|
|
/// </summary>
|
|
|
- public static readonly DirectProperty<DatePicker, DateTimeOffset?> SelectedDateProperty =
|
|
|
- AvaloniaProperty.RegisterDirect<DatePicker, DateTimeOffset?>(nameof(SelectedDate),
|
|
|
- x => x.SelectedDate, (x, v) => x.SelectedDate = v,
|
|
|
+ public static readonly StyledProperty<DateTimeOffset?> SelectedDateProperty =
|
|
|
+ AvaloniaProperty.Register<DatePicker, DateTimeOffset?>(nameof(SelectedDate),
|
|
|
defaultBindingMode: BindingMode.TwoWay);
|
|
|
|
|
|
// Template Items
|
|
@@ -103,28 +93,20 @@ namespace Avalonia.Controls
|
|
|
|
|
|
private bool _areControlsAvailable;
|
|
|
|
|
|
- private string _dayFormat = "%d";
|
|
|
- private bool _dayVisible = true;
|
|
|
- private DateTimeOffset _maxYear;
|
|
|
- private DateTimeOffset _minYear;
|
|
|
- private string _monthFormat = "MMMM";
|
|
|
- private bool _monthVisible = true;
|
|
|
- private string _yearFormat = "yyyy";
|
|
|
- private bool _yearVisible = true;
|
|
|
- private DateTimeOffset? _selectedDate;
|
|
|
-
|
|
|
public DatePicker()
|
|
|
{
|
|
|
PseudoClasses.Set(":hasnodate", true);
|
|
|
var now = DateTimeOffset.Now;
|
|
|
- _minYear = new DateTimeOffset(now.Date.Year - 100, 1, 1, 0, 0, 0, now.Offset);
|
|
|
- _maxYear = new DateTimeOffset(now.Date.Year + 100, 12, 31, 0, 0, 0, now.Offset);
|
|
|
+ SetCurrentValue(MinYearProperty, new DateTimeOffset(now.Date.Year - 100, 1, 1, 0, 0, 0, now.Offset));
|
|
|
+ SetCurrentValue(MaxYearProperty, new DateTimeOffset(now.Date.Year + 100, 12, 31, 0, 0, 0, now.Offset));
|
|
|
}
|
|
|
|
|
|
+ private static void OnGridVisibilityChanged(DatePicker sender, AvaloniaPropertyChangedEventArgs e) => sender.SetGrid();
|
|
|
+
|
|
|
public string DayFormat
|
|
|
{
|
|
|
- get => _dayFormat;
|
|
|
- set => SetAndRaise(DayFormatProperty, ref _dayFormat, value);
|
|
|
+ get => GetValue(DayFormatProperty);
|
|
|
+ set => SetValue(DayFormatProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -132,12 +114,8 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public bool DayVisible
|
|
|
{
|
|
|
- get => _dayVisible;
|
|
|
- set
|
|
|
- {
|
|
|
- SetAndRaise(DayVisibleProperty, ref _dayVisible, value);
|
|
|
- SetGrid();
|
|
|
- }
|
|
|
+ get => GetValue(DayVisibleProperty);
|
|
|
+ set => SetValue(DayVisibleProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -145,16 +123,24 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public DateTimeOffset MaxYear
|
|
|
{
|
|
|
- get => _maxYear;
|
|
|
- set
|
|
|
- {
|
|
|
- if (value < MinYear)
|
|
|
- throw new InvalidOperationException("MaxDate cannot be less than MinDate");
|
|
|
- SetAndRaise(MaxYearProperty, ref _maxYear, value);
|
|
|
+ get => GetValue(MaxYearProperty);
|
|
|
+ set => SetValue(MaxYearProperty, value);
|
|
|
+ }
|
|
|
|
|
|
- if (SelectedDate.HasValue && SelectedDate.Value > value)
|
|
|
- SelectedDate = value;
|
|
|
+ private static DateTimeOffset CoerceMaxYear(AvaloniaObject sender, DateTimeOffset value)
|
|
|
+ {
|
|
|
+ if (value < sender.GetValue(MinYearProperty))
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException($"{MaxYearProperty.Name} cannot be less than {MinYearProperty.Name}");
|
|
|
}
|
|
|
+
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnMaxYearChanged(DateTimeOffset? value)
|
|
|
+ {
|
|
|
+ if (SelectedDate.HasValue && SelectedDate.Value > value)
|
|
|
+ SetCurrentValue(SelectedDateProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -162,16 +148,24 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public DateTimeOffset MinYear
|
|
|
{
|
|
|
- get => _minYear;
|
|
|
- set
|
|
|
- {
|
|
|
- if (value > MaxYear)
|
|
|
- throw new InvalidOperationException("MinDate cannot be greater than MaxDate");
|
|
|
- SetAndRaise(MinYearProperty, ref _minYear, value);
|
|
|
+ get => GetValue(MinYearProperty);
|
|
|
+ set => SetValue(MinYearProperty, value);
|
|
|
+ }
|
|
|
|
|
|
- if (SelectedDate.HasValue && SelectedDate.Value < value)
|
|
|
- SelectedDate = value;
|
|
|
+ private static DateTimeOffset CoerceMinYear(AvaloniaObject sender, DateTimeOffset value)
|
|
|
+ {
|
|
|
+ if (value > sender.GetValue(MaxYearProperty))
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException($"{MinYearProperty.Name} cannot be greater than {MaxYearProperty.Name}");
|
|
|
}
|
|
|
+
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void OnMinYearChanged(DateTimeOffset? value)
|
|
|
+ {
|
|
|
+ if (SelectedDate.HasValue && SelectedDate.Value < value)
|
|
|
+ SetCurrentValue(SelectedDateProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -179,8 +173,8 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public string MonthFormat
|
|
|
{
|
|
|
- get => _monthFormat;
|
|
|
- set => SetAndRaise(MonthFormatProperty, ref _monthFormat, value);
|
|
|
+ get => GetValue(MonthFormatProperty);
|
|
|
+ set => SetValue(MonthFormatProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -188,12 +182,8 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public bool MonthVisible
|
|
|
{
|
|
|
- get => _monthVisible;
|
|
|
- set
|
|
|
- {
|
|
|
- SetAndRaise(MonthVisibleProperty, ref _monthVisible, value);
|
|
|
- SetGrid();
|
|
|
- }
|
|
|
+ get => GetValue(MonthVisibleProperty);
|
|
|
+ set => SetValue(MonthVisibleProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -201,8 +191,8 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public string YearFormat
|
|
|
{
|
|
|
- get => _yearFormat;
|
|
|
- set => SetAndRaise(YearFormatProperty, ref _yearFormat, value);
|
|
|
+ get => GetValue(YearFormatProperty);
|
|
|
+ set => SetValue(YearFormatProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -210,12 +200,8 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public bool YearVisible
|
|
|
{
|
|
|
- get => _yearVisible;
|
|
|
- set
|
|
|
- {
|
|
|
- SetAndRaise(YearVisibleProperty, ref _yearVisible, value);
|
|
|
- SetGrid();
|
|
|
- }
|
|
|
+ get => GetValue(YearVisibleProperty);
|
|
|
+ set => SetValue(YearVisibleProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -223,14 +209,8 @@ namespace Avalonia.Controls
|
|
|
/// </summary>
|
|
|
public DateTimeOffset? SelectedDate
|
|
|
{
|
|
|
- get => _selectedDate;
|
|
|
- set
|
|
|
- {
|
|
|
- var old = _selectedDate;
|
|
|
- SetAndRaise(SelectedDateProperty, ref _selectedDate, value);
|
|
|
- SetSelectedDateText();
|
|
|
- OnSelectedDateChanged(this, new DatePickerSelectedValueChangedEventArgs(old, value));
|
|
|
- }
|
|
|
+ get => GetValue(SelectedDateProperty);
|
|
|
+ set => SetValue(SelectedDateProperty, value);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -287,6 +267,31 @@ namespace Avalonia.Controls
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
|
+ {
|
|
|
+ base.OnPropertyChanged(change);
|
|
|
+
|
|
|
+ if (change.Property == DayVisibleProperty || change.Property == MonthVisibleProperty || change.Property == YearVisibleProperty)
|
|
|
+ {
|
|
|
+ SetGrid();
|
|
|
+ }
|
|
|
+ else if (change.Property == MaxYearProperty)
|
|
|
+ {
|
|
|
+ OnMaxYearChanged(change.GetNewValue<DateTimeOffset>());
|
|
|
+ }
|
|
|
+ else if (change.Property == MinYearProperty)
|
|
|
+ {
|
|
|
+ OnMinYearChanged(change.GetNewValue<DateTimeOffset>());
|
|
|
+ }
|
|
|
+ else if (change.Property == SelectedDateProperty)
|
|
|
+ {
|
|
|
+ SetSelectedDateText();
|
|
|
+
|
|
|
+ var (oldValue, newValue) = change.GetOldAndNewValue<DateTimeOffset?>();
|
|
|
+ OnSelectedDateChanged(this, new DatePickerSelectedValueChangedEventArgs(oldValue, newValue));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private void OnDismissPicker(object? sender, EventArgs e)
|
|
|
{
|
|
|
_popup!.Close();
|
|
@@ -296,7 +301,7 @@ namespace Avalonia.Controls
|
|
|
private void OnConfirmed(object? sender, EventArgs e)
|
|
|
{
|
|
|
_popup!.Close();
|
|
|
- SelectedDate = _presenter!.Date;
|
|
|
+ SetCurrentValue(SelectedDateProperty, _presenter!.Date);
|
|
|
}
|
|
|
|
|
|
private void SetGrid()
|