@ -1,6 +1,5 @@
using Avalonia.Controls.Metadata ;
using Avalonia.Controls.Metadata ;
using Avalonia.Controls.Primitives ;
using Avalonia.Controls.Primitives ;
using Avalonia.Controls.Shapes ;
using Avalonia.Input ;
using Avalonia.Input ;
using Avalonia.Interactivity ;
using Avalonia.Interactivity ;
using System ;
using System ;
@ -13,23 +12,23 @@ namespace Avalonia.Controls
/// Defines the presenter used for selecting a date for a
/// Defines the presenter used for selecting a date for a
/// <see cref="DatePicker"/>
/// <see cref="DatePicker"/>
/// </summary>
/// </summary>
[TemplatePart("PART_AcceptButton" , typeof(Button), IsRequired = true)]
[TemplatePart(TemplateItems.AcceptButtonName , typeof(Button), IsRequired = true)]
[TemplatePart("PART_DayDownButton", typeof(Repeat Button))]
[TemplatePart(TemplateItems.DayDownButtonName, typeof( Button))]
[TemplatePart("PART_DayHost" , typeof(Panel), IsRequired = true)]
[TemplatePart(TemplateItems.DayHostName , typeof(Panel), IsRequired = true)]
[TemplatePart("PART_DaySelector" , typeof(DateTimePickerPanel), IsRequired = true)]
[TemplatePart(TemplateItems.DaySelectorName , typeof(DateTimePickerPanel), IsRequired = true)]
[TemplatePart("PART_DayUpButton", typeof(Repeat Button))]
[TemplatePart(TemplateItems.DayUpButtonName, typeof( Button))]
[TemplatePart("PART_DismissButton" , typeof(Button))]
[TemplatePart(TemplateItems.DismissButtonName , typeof(Button))]
[TemplatePart("PART_FirstSpacer", typeof(Rectangle ))]
[TemplatePart(TemplateItems.FirstSpacerName, typeof(Control ))]
[TemplatePart("PART_MonthDownButton", typeof(Repeat Button))]
[TemplatePart(TemplateItems.MonthDownButtonName, typeof( Button))]
[TemplatePart("PART_MonthHost" , typeof(Panel), IsRequired = true)]
[TemplatePart(TemplateItems.MonthHostName , typeof(Panel), IsRequired = true)]
[TemplatePart("PART_MonthSelector" , typeof(DateTimePickerPanel), IsRequired = true)]
[TemplatePart(TemplateItems.MonthSelectorName , typeof(DateTimePickerPanel), IsRequired = true)]
[TemplatePart("PART_MonthUpButton", typeof(Repeat Button))]
[TemplatePart(TemplateItems.MonthUpButtonName, typeof( Button))]
[TemplatePart("PART_PickerContainer" , typeof(Grid), IsRequired = true)]
[TemplatePart(TemplateItems.PickerContainerName , typeof(Grid), IsRequired = true)]
[TemplatePart("PART_SecondSpacer", typeof(Rectangle ))]
[TemplatePart(TemplateItems.SecondSpacerName, typeof(Control ))]
[TemplatePart("PART_YearDownButton", typeof(Repeat Button))]
[TemplatePart(TemplateItems.YearDownButtonName, typeof( Button))]
[TemplatePart("PART_YearHost" , typeof(Panel), IsRequired = true)]
[TemplatePart(TemplateItems.YearHostName , typeof(Panel), IsRequired = true)]
[TemplatePart("PART_YearSelector" , typeof(DateTimePickerPanel), IsRequired = true)]
[TemplatePart(TemplateItems.YearSelectorName , typeof(DateTimePickerPanel), IsRequired = true)]
[TemplatePart("PART_YearUpButton", typeof(Repeat Button))]
[TemplatePart(TemplateItems.YearUpButtonName, typeof( Button))]
public class DatePickerPresenter : PickerPresenterBase
public class DatePickerPresenter : PickerPresenterBase
{
{
/// <summary>
/// <summary>
@ -102,24 +101,61 @@ namespace Avalonia.Controls
public static readonly StyledProperty < bool > YearVisibleProperty =
public static readonly StyledProperty < bool > YearVisibleProperty =
DatePicker . YearVisibleProperty . AddOwner < DatePickerPresenter > ( ) ;
DatePicker . YearVisibleProperty . AddOwner < DatePickerPresenter > ( ) ;
// Template Items
private struct TemplateItems
private Grid ? _ pickerContainer ;
{
private Button ? _ acceptButton ;
public Grid _ pickerContainer ;
private Button ? _d ismissButton ;
public const string PickerContainerName = "PART_PickerContainer" ;
private Rectangle ? _ spacer1 ;
private Rectangle ? _ spacer2 ;
public Button _ acceptButton ;
private Panel ? _ monthHost ;
public const string AcceptButtonName = "PART_AcceptButton" ;
private Panel ? _ yearHost ;
private Panel ? _d ayHost ;
public Button ? _d ismissButton ;
private DateTimePickerPanel ? _ monthSelector ;
public const string DismissButtonName = "PART_DismissButton" ;
private DateTimePickerPanel ? _ yearSelector ;
private DateTimePickerPanel ? _d aySelector ;
public Control ? _f irstSpacer ;
private Button ? _ monthUpButton ;
public const string FirstSpacerName = "PART_FirstSpacer" ;
private Button ? _d ayUpButton ;
private Button ? _ yearUpButton ;
public Control ? _ secondSpacer ;
private Button ? _ monthDownButton ;
public const string SecondSpacerName = "PART_SecondSpacer" ;
private Button ? _d ayDownButton ;
private Button ? _ yearDownButton ;
public Panel _ monthHost ;
public const string MonthHostName = "PART_MonthHost" ;
public Panel _ yearHost ;
public const string YearHostName = "PART_YearHost" ;
public Panel _d ayHost ;
public const string DayHostName = "PART_DayHost" ;
public DateTimePickerPanel _ monthSelector ;
public const string MonthSelectorName = "PART_MonthSelector" ;
public DateTimePickerPanel _ yearSelector ;
public const string YearSelectorName = "PART_YearSelector" ;
public DateTimePickerPanel _d aySelector ;
public const string DaySelectorName = "PART_DaySelector" ;
public Button ? _ monthUpButton ;
public const string MonthUpButtonName = "PART_MonthUpButton" ;
public Button ? _d ayUpButton ;
public const string DayUpButtonName = "PART_DayUpButton" ;
public Button ? _ yearUpButton ;
public const string YearUpButtonName = "PART_YearUpButton" ;
public Button ? _ monthDownButton ;
public const string MonthDownButtonName = "PART_MonthDownButton" ;
public Button ? _d ayDownButton ;
public const string DayDownButtonName = "PART_DayDownButton" ;
public Button ? _ yearDownButton ;
public const string YearDownButtonName = "PART_YearDownButton" ;
}
private TemplateItems ? _ templateItems ;
private DateTimeOffset _ syncDate ;
private DateTimeOffset _ syncDate ;
@ -235,69 +271,54 @@ namespace Avalonia.Controls
protected override void OnApplyTemplate ( TemplateAppliedEventArgs e )
protected override void OnApplyTemplate ( TemplateAppliedEventArgs e )
{
{
base . OnApplyTemplate ( e ) ;
base . OnApplyTemplate ( e ) ;
// These are requirements, so throw if not found
_ pickerContainer = e . NameScope . Get < Grid > ( "PART_PickerContainer" ) ;
_ monthHost = e . NameScope . Get < Panel > ( "PART_MonthHost" ) ;
_d ayHost = e . NameScope . Get < Panel > ( "PART_DayHost" ) ;
_ yearHost = e . NameScope . Get < Panel > ( "PART_YearHost" ) ;
_ monthSelector = e . NameScope . Get < DateTimePickerPanel > ( "PART_MonthSelector" ) ;
_ templateItems = new ( )
_ monthSelector . SelectionChanged + = OnMonthChanged ;
_d aySelector = e . NameScope . Get < DateTimePickerPanel > ( "PART_DaySelector" ) ;
_d aySelector . SelectionChanged + = OnDayChanged ;
_ yearSelector = e . NameScope . Get < DateTimePickerPanel > ( "PART_YearSelector" ) ;
_ yearSelector . SelectionChanged + = OnYearChanged ;
_ acceptButton = e . NameScope . Get < Button > ( "PART_AcceptButton" ) ;
_ monthUpButton = e . NameScope . Find < RepeatButton > ( "PART_MonthUpButton" ) ;
if ( _ monthUpButton ! = null )
{
_ monthUpButton . Click + = OnSelectorButtonClick ;
}
_ monthDownButton = e . NameScope . Find < RepeatButton > ( "PART_MonthDownButton" ) ;
if ( _ monthDownButton ! = null )
{
{
_ monthDownButton . Click + = OnSelectorButtonClick ;
// These are requirements, so throw if not found
}
_ pickerContainer = e . NameScope . Get < Grid > ( TemplateItems . PickerContainerName ) ,
_ monthHost = e . NameScope . Get < Panel > ( TemplateItems . MonthHostName ) ,
_d ayHost = e . NameScope . Get < Panel > ( TemplateItems . DayHostName ) ,
_ yearHost = e . NameScope . Get < Panel > ( TemplateItems . YearHostName ) ,
_ monthSelector = e . NameScope . Get < DateTimePickerPanel > ( TemplateItems . MonthSelectorName ) ,
_d aySelector = e . NameScope . Get < DateTimePickerPanel > ( TemplateItems . DaySelectorName ) ,
_ yearSelector = e . NameScope . Get < DateTimePickerPanel > ( TemplateItems . YearSelectorName ) ,
_ acceptButton = e . NameScope . Get < Button > ( TemplateItems . AcceptButtonName ) ,
_ monthUpButton = SelectorButton ( TemplateItems . MonthUpButtonName , DateTimePickerPanelType . Month , SpinDirection . Decrease ) ,
_ monthDownButton = SelectorButton ( TemplateItems . MonthDownButtonName , DateTimePickerPanelType . Month , SpinDirection . Increase ) ,
_d ayUpButton = SelectorButton ( TemplateItems . DayUpButtonName , DateTimePickerPanelType . Day , SpinDirection . Decrease ) ,
_d ayDownButton = SelectorButton ( TemplateItems . DayDownButtonName , DateTimePickerPanelType . Day , SpinDirection . Increase ) ,
_ yearUpButton = SelectorButton ( TemplateItems . YearUpButtonName , DateTimePickerPanelType . Year , SpinDirection . Decrease ) ,
_ yearDownButton = SelectorButton ( TemplateItems . YearDownButtonName , DateTimePickerPanelType . Year , SpinDirection . Increase ) ,
_d ismissButton = e . NameScope . Find < Button > ( TemplateItems . DismissButtonName ) ,
_f irstSpacer = e . NameScope . Find < Control > ( TemplateItems . FirstSpacerName ) ,
_ secondSpacer = e . NameScope . Find < Control > ( TemplateItems . SecondSpacerName ) ,
} ;
_d ayUpButton = e . NameScope . Find < RepeatButton > ( "PART_DayUpButton" ) ;
_ templateItems . Value . _ acceptButton . Click + = OnAcceptButtonClicked ;
if ( _d ayUpButton ! = null )
_ templateItems . Value . _ monthSelector . SelectionChanged + = OnMonthChanged ;
{
_ templateItems . Value . _d aySelector . SelectionChanged + = OnDayChanged ;
_d ayUpButton . Click + = OnSelectorButtonClick ;
_ templateItems . Value . _ yearSelector . SelectionChanged + = OnYearChanged ;
}
_d ayDownButton = e . NameScope . Find < RepeatButton > ( "PART_DayDownButton" ) ;
if ( _d ayDownButton ! = null )
{
_d ayDownButton . Click + = OnSelectorButtonClick ;
}
_ yearUpButton = e . NameScope . Find < RepeatButton > ( "PART_YearUpButton" ) ;
if ( _ templateItems . Value . _d ismissButton is { } dismissButton )
if ( _ yearUpButton ! = null )
{
{
_ yearUpButton . Click + = OnSelectorButtonClick ;
dismissButton . Click + = OnDismissButtonClicked ;
}
_ yearDownButton = e . NameScope . Find < RepeatButton > ( "PART_YearDownButton" ) ;
if ( _ yearDownButton ! = null )
{
_ yearDownButton . Click + = OnSelectorButtonClick ;
}
}
_d ismissButton = e . NameScope . Find < Button > ( "PART_DismissButton" ) ;
InitPicker ( ) ;
_ spacer1 = e . NameScope . Find < Rectangle > ( "PART_FirstSpacer" ) ;
_ spacer2 = e . NameScope . Find < Rectangle > ( "PART_SecondSpacer" ) ;
if ( _ acceptButton ! = null )
Button ? SelectorButton ( string name , DateTimePickerPanelType type , SpinDirection direction )
{
_ acceptButton . Click + = OnAcceptButtonClicked ;
}
if ( _d ismissButton ! = null )
{
{
_d ismissButton . Click + = OnDismissButtonClicked ;
if ( e . NameScope . Find < Button > ( name ) is { } button )
{
button . Click + = ( s , e ) = > OnSelectorButtonClick ( type , direction ) ;
return button ;
}
return null ;
}
}
InitPicker ( ) ;
}
}
protected override void OnPropertyChanged ( AvaloniaPropertyChangedEventArgs change )
protected override void OnPropertyChanged ( AvaloniaPropertyChangedEventArgs change )
@ -350,63 +371,63 @@ namespace Avalonia.Controls
private void InitPicker ( )
private void InitPicker ( )
{
{
// OnApplyTemplate must've been called before we can init here...
// OnApplyTemplate must've been called before we can init here...
if ( _ pickerContainer = = null )
if ( _ templateItems is not { } items )
return ;
return ;
_ suppressUpdateSelection = true ;
_ suppressUpdateSelection = true ;
_ monthSelector ! . MaximumValue = 1 2 ;
items . _ monthSelector . MaximumValue = 1 2 ;
_ monthSelector . MinimumValue = 1 ;
items . _ monthSelector . MinimumValue = 1 ;
_ monthSelector . ItemFormat = MonthFormat ;
items . _ monthSelector . ItemFormat = MonthFormat ;
_d aySelector ! . ItemFormat = DayFormat ;
items . _d aySelector . ItemFormat = DayFormat ;
_ yearSelector ! . MaximumValue = MaxYear . Year ;
items . _ yearSelector . MaximumValue = MaxYear . Year ;
_ yearSelector . MinimumValue = MinYear . Year ;
items . _ yearSelector . MinimumValue = MinYear . Year ;
_ yearSelector . ItemFormat = YearFormat ;
items . _ yearSelector . ItemFormat = YearFormat ;
SetGrid ( ) ;
SetGrid ( items ) ;
// Date should've been set when we reach this point
// Date should've been set when we reach this point
var dt = Date ;
var dt = Date ;
if ( DayVisible )
if ( DayVisible )
{
{
_d aySelector . FormatDate = dt . Date ;
items . _d aySelector . FormatDate = dt . Date ;
var maxDays = _ calendar . GetDaysInMonth ( dt . Year , dt . Month ) ;
var maxDays = _ calendar . GetDaysInMonth ( dt . Year , dt . Month ) ;
_d aySelector . MaximumValue = maxDays ;
items . _d aySelector . MaximumValue = maxDays ;
_d aySelector . MinimumValue = 1 ;
items . _d aySelector . MinimumValue = 1 ;
_d aySelector . SelectedValue = dt . Day ;
items . _d aySelector . SelectedValue = dt . Day ;
}
}
if ( MonthVisible )
if ( MonthVisible )
{
{
_ monthSelector . SelectedValue = dt . Month ;
items . _ monthSelector . SelectedValue = dt . Month ;
_ monthSelector . FormatDate = dt . Date ;
items . _ monthSelector . FormatDate = dt . Date ;
}
}
if ( YearVisible )
if ( YearVisible )
{
{
_ yearSelector . SelectedValue = dt . Year ;
items . _ yearSelector . SelectedValue = dt . Year ;
_ yearSelector . FormatDate = dt . Date ;
items . _ yearSelector . FormatDate = dt . Date ;
}
}
_ suppressUpdateSelection = false ;
_ suppressUpdateSelection = false ;
SetInitialFocus ( ) ;
SetInitialFocus ( items ) ;
}
}
private void SetGrid ( )
private void SetGrid ( TemplateItems items )
{
{
var fmt = CultureInfo . CurrentCulture . DateTimeFormat . ShortDatePattern ;
var fmt = CultureInfo . CurrentCulture . DateTimeFormat . ShortDatePattern ;
var columns = new List < ( Panel ? , int ) >
var columns = new List < ( Panel ? , int ) >
{
{
( _ monthHost , MonthVisible ? fmt . IndexOf ( "m" , StringComparison . OrdinalIgnoreCase ) : - 1 ) ,
( items . _ monthHost , MonthVisible ? fmt . IndexOf ( "m" , StringComparison . OrdinalIgnoreCase ) : - 1 ) ,
( _ yearHost , YearVisible ? fmt . IndexOf ( "y" , StringComparison . OrdinalIgnoreCase ) : - 1 ) ,
( items . _ yearHost , YearVisible ? fmt . IndexOf ( "y" , StringComparison . OrdinalIgnoreCase ) : - 1 ) ,
( _d ayHost , DayVisible ? fmt . IndexOf ( "d" , StringComparison . OrdinalIgnoreCase ) : - 1 ) ,
( items . _d ayHost , DayVisible ? fmt . IndexOf ( "d" , StringComparison . OrdinalIgnoreCase ) : - 1 ) ,
} ;
} ;
columns . Sort ( ( x , y ) = > x . Item2 - y . Item2 ) ;
columns . Sort ( ( x , y ) = > x . Item2 - y . Item2 ) ;
_ pickerContainer ! . ColumnDefinitions . Clear ( ) ;
items . _ pickerContainer . ColumnDefinitions . Clear ( ) ;
var columnIndex = 0 ;
var columnIndex = 0 ;
@ -421,48 +442,53 @@ namespace Avalonia.Controls
{
{
if ( columnIndex > 0 )
if ( columnIndex > 0 )
{
{
_ pickerContainer . ColumnDefinitions . Add ( new ColumnDefinition ( 0 , GridUnitType . Auto ) ) ;
items . _ pickerContainer . ColumnDefinitions . Add ( new ColumnDefinition ( 0 , GridUnitType . Auto ) ) ;
}
}
_ pickerContainer . ColumnDefinitions . Add (
items . _ pickerContainer . ColumnDefinitions . Add (
new ColumnDefinition ( column . Item1 = = _ monthHost ? 1 3 8 : 7 8 , GridUnitType . Star ) ) ;
new ColumnDefinition ( column . Item1 = = items . _ monthHost ? 1 3 8 : 7 8 , GridUnitType . Star ) ) ;
if ( column . Item1 . Parent is null )
if ( column . Item1 . Parent is null )
{
{
_ pickerContainer . Children . Add ( column . Item1 ) ;
items . _ pickerContainer . Children . Add ( column . Item1 ) ;
}
}
Grid . SetColumn ( column . Item1 , ( columnIndex + + * 2 ) ) ;
Grid . SetColumn ( column . Item1 , ( columnIndex + + * 2 ) ) ;
}
}
}
}
var isSpacer1Visible = columnIndex > 1 ;
ConfigureSpacer ( items . _f irstSpacer , columnIndex > 1 ) ;
var isSpacer2Visible = columnIndex > 2 ;
ConfigureSpacer ( items . _ secondSpacer , columnIndex > 2 ) ;
// ternary conditional operator is used to make sure grid cells will be validated
Grid . SetColumn ( _ spacer1 ! , isSpacer1Visible ? 1 : 0 ) ;
static void ConfigureSpacer ( Control ? spacer , bool visible )
Grid . SetColumn ( _ spacer2 ! , isSpacer2Visible ? 3 : 0 ) ;
{
if ( spacer = = null )
return ;
// ternary conditional operator is used to make sure grid cells will be validated
Grid . SetColumn ( spacer , visible ? 1 : 0 ) ;
spacer . IsVisible = visible ;
_ spacer1 ! . IsVisible = isSpacer1Visible ;
}
_ spacer2 ! . IsVisible = isSpacer2Visible ;
}
}
private void SetInitialFocus ( )
private void SetInitialFocus ( TemplateItems items )
{
{
int monthCol = MonthVisible ? Grid . GetColumn ( _ monthHost ! ) : int . MaxValue ;
int monthCol = MonthVisible ? Grid . GetColumn ( items . _ monthHost ) : int . MaxValue ;
int dayCol = DayVisible ? Grid . GetColumn ( _d ayHost ! ) : int . MaxValue ;
int dayCol = DayVisible ? Grid . GetColumn ( items . _d ayHost ) : int . MaxValue ;
int yearCol = YearVisible ? Grid . GetColumn ( _ yearHost ! ) : int . MaxValue ;
int yearCol = YearVisible ? Grid . GetColumn ( items . _ yearHost ) : int . MaxValue ;
if ( monthCol < dayCol & & monthCol < yearCol )
if ( monthCol < dayCol & & monthCol < yearCol )
{
{
_ monthSelector ? . Focus ( NavigationMethod . Pointer ) ;
items . _ monthSelector . Focus ( NavigationMethod . Pointer ) ;
}
}
else if ( dayCol < monthCol & & dayCol < yearCol )
else if ( dayCol < monthCol & & dayCol < yearCol )
{
{
_ monthSelector ? . Focus ( NavigationMethod . Pointer ) ;
items . _ monthSelector . Focus ( NavigationMethod . Pointer ) ;
}
}
else if ( yearCol < monthCol & & yearCol < dayCol )
else if ( yearCol < monthCol & & yearCol < dayCol )
{
{
_ yearSelector ? . Focus ( NavigationMethod . Pointer ) ;
items . _ yearSelector . Focus ( NavigationMethod . Pointer ) ;
}
}
}
}
@ -477,29 +503,36 @@ namespace Avalonia.Controls
OnConfirmed ( ) ;
OnConfirmed ( ) ;
}
}
private void OnSelectorButtonClick ( object? sender , RoutedEventArgs e )
private void OnSelectorButtonClick ( DateTimePickerPanelType type , SpinDirection direction )
{
{
if ( sender = = _ monthUpButton )
var target = type switch
_ monthSelector ! . ScrollUp ( ) ;
{
else if ( sender = = _ monthDownButton )
DateTimePickerPanelType . Month = > _ templateItems ? . _ monthSelector ,
_ monthSelector ! . ScrollDown ( ) ;
DateTimePickerPanelType . Day = > _ templateItems ? . _d aySelector ,
else if ( sender = = _ yearUpButton )
DateTimePickerPanelType . Year = > _ templateItems ? . _ yearSelector ,
_ yearSelector ! . ScrollUp ( ) ;
_ = > throw new NotImplementedException ( ) ,
else if ( sender = = _ yearDownButton )
} ;
_ yearSelector ! . ScrollDown ( ) ;
else if ( sender = = _d ayUpButton )
switch ( direction )
_d aySelector ! . ScrollUp ( ) ;
{
else if ( sender = = _d ayDownButton )
case SpinDirection . Increase :
_d aySelector ! . ScrollDown ( ) ;
target ? . ScrollDown ( ) ;
break ;
case SpinDirection . Decrease :
target ? . ScrollUp ( ) ;
break ;
default :
throw new NotImplementedException ( ) ;
}
}
}
private void OnYearChanged ( object? sender , EventArgs e )
private void OnYearChanged ( object? sender , EventArgs e )
{
{
if ( _ suppressUpdateSelection )
if ( _ suppressUpdateSelection | | _ templateItems is not { } items )
return ;
return ;
int maxDays = _ calendar . GetDaysInMonth ( _ yearSelector ! . SelectedValue , _ syncDate . Month ) ;
int maxDays = _ calendar . GetDaysInMonth ( items . _ yearSelector . SelectedValue , _ syncDate . Month ) ;
var newDate = new DateTimeOffset ( _ yearSelector . SelectedValue , _ syncDate . Month ,
var newDate = new DateTimeOffset ( items . _ yearSelector . SelectedValue , _ syncDate . Month ,
_ syncDate . Day > maxDays ? maxDays : _ syncDate . Day , 0 , 0 , 0 , _ syncDate . Offset ) ;
_ syncDate . Day > maxDays ? maxDays : _ syncDate . Day , 0 , 0 , 0 , _ syncDate . Offset ) ;
_ syncDate = newDate ;
_ syncDate = newDate ;
@ -510,30 +543,30 @@ namespace Avalonia.Controls
_ suppressUpdateSelection = true ;
_ suppressUpdateSelection = true ;
_d aySelector ! . FormatDate = newDate . Date ;
items . _d aySelector . FormatDate = newDate . Date ;
if ( _d aySelector . MaximumValue ! = maxDays )
if ( items . _d aySelector . MaximumValue ! = maxDays )
_d aySelector . MaximumValue = maxDays ;
items . _d aySelector . MaximumValue = maxDays ;
else
else
_d aySelector . RefreshItems ( ) ;
items . _d aySelector . RefreshItems ( ) ;
_ suppressUpdateSelection = false ;
_ suppressUpdateSelection = false ;
}
}
private void OnDayChanged ( object? sender , EventArgs e )
private void OnDayChanged ( object? sender , EventArgs e )
{
{
if ( _ suppressUpdateSelection )
if ( _ suppressUpdateSelection | | _ templateItems is not { } items )
return ;
return ;
_ syncDate = new DateTimeOffset ( _ syncDate . Year , _ syncDate . Month , _d aySelector ! . SelectedValue , 0 , 0 , 0 , _ syncDate . Offset ) ;
_ syncDate = new DateTimeOffset ( _ syncDate . Year , _ syncDate . Month , items . _d aySelector . SelectedValue , 0 , 0 , 0 , _ syncDate . Offset ) ;
}
}
private void OnMonthChanged ( object? sender , EventArgs e )
private void OnMonthChanged ( object? sender , EventArgs e )
{
{
if ( _ suppressUpdateSelection )
if ( _ suppressUpdateSelection | | _ templateItems is not { } items )
return ;
return ;
int maxDays = _ calendar . GetDaysInMonth ( _ syncDate . Year , _ monthSelector ! . SelectedValue ) ;
int maxDays = _ calendar . GetDaysInMonth ( _ syncDate . Year , items . _ monthSelector . SelectedValue ) ;
var newDate = new DateTimeOffset ( _ syncDate . Year , _ monthSelector . SelectedValue ,
var newDate = new DateTimeOffset ( _ syncDate . Year , items . _ monthSelector . SelectedValue ,
_ syncDate . Day > maxDays ? maxDays : _ syncDate . Day , 0 , 0 , 0 , _ syncDate . Offset ) ;
_ syncDate . Day > maxDays ? maxDays : _ syncDate . Day , 0 , 0 , 0 , _ syncDate . Offset ) ;
if ( ! DayVisible )
if ( ! DayVisible )
@ -544,24 +577,24 @@ namespace Avalonia.Controls
_ suppressUpdateSelection = true ;
_ suppressUpdateSelection = true ;
_d aySelector ! . FormatDate = newDate . Date ;
items . _d aySelector . FormatDate = newDate . Date ;
_ syncDate = newDate ;
_ syncDate = newDate ;
if ( _d aySelector . MaximumValue ! = maxDays )
if ( items . _d aySelector . MaximumValue ! = maxDays )
_d aySelector . MaximumValue = maxDays ;
items . _d aySelector . MaximumValue = maxDays ;
else
else
_d aySelector . RefreshItems ( ) ;
items . _d aySelector . RefreshItems ( ) ;
_ suppressUpdateSelection = false ;
_ suppressUpdateSelection = false ;
}
}
internal double GetOffsetForPopup ( )
internal double GetOffsetForPopup ( )
{
{
if ( _ monthSelector is null )
if ( _ templateItems is not { } items )
return 0 ;
return 0 ;
var acceptDismissButtonHeight = _ acceptButton ! = null ? _ acceptButton . Bounds . Height : 4 1 ;
var acceptDismissButtonHeight = items . _ acceptButton . Bounds . Height ;
return - ( MaxHeight - acceptDismissButtonHeight ) / 2 - ( _ monthSelector . ItemHeight / 2 ) ;
return - ( MaxHeight - acceptDismissButtonHeight ) / 2 - ( items . _ monthSelector . ItemHeight / 2 ) ;
}
}
}
}
}
}