Skip to content

Commit 4b6d122

Browse files
maxkatz6danwalmsley
authored andcommitted
Merge pull request AvaloniaUI#7634 from AvaloniaUI/fixes/7633-date-time-picker-popup
Fix Date/Time picker popups # Conflicts: # src/Avalonia.Controls/DateTimePickers/DatePicker.cs # src/Avalonia.Controls/DateTimePickers/TimePicker.cs
1 parent 0419426 commit 4b6d122

File tree

4 files changed

+36
-7
lines changed

4 files changed

+36
-7
lines changed

src/Avalonia.Controls/DateTimePickers/DatePicker.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Avalonia.Controls.Templates;
55
using Avalonia.Data;
66
using Avalonia.Interactivity;
7+
using Avalonia.Layout;
78
using System;
89
using System.Collections.Generic;
910
using System.Globalization;
@@ -398,18 +399,27 @@ private void SetSelectedDateText()
398399
private void OnFlyoutButtonClicked(object sender, RoutedEventArgs e)
399400
{
400401
if (_presenter == null)
401-
throw new InvalidOperationException("No DatePickerPresenter found");
402+
throw new InvalidOperationException("No DatePickerPresenter found.");
403+
if (_popup == null)
404+
throw new InvalidOperationException("No Popup found.");
402405

403406
_presenter.Date = SelectedDate ?? DateTimeOffset.Now;
404407

408+
_popup.PlacementMode = PlacementMode.AnchorAndGravity;
409+
_popup.PlacementAnchor = Primitives.PopupPositioning.PopupAnchor.Bottom;
410+
_popup.PlacementGravity = Primitives.PopupPositioning.PopupGravity.Bottom;
411+
_popup.PlacementConstraintAdjustment = Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY;
405412
_popup.IsOpen = true;
406413

414+
// Overlay popup hosts won't get measured until the next layout pass, but we need the
415+
// template to be applied to `_presenter` now. Detect this case and force a layout pass.
416+
if (!_presenter.IsMeasureValid)
417+
(VisualRoot as ILayoutRoot)?.LayoutManager?.ExecuteInitialLayoutPass();
418+
407419
var deltaY = _presenter.GetOffsetForPopup();
408420

409421
// The extra 5 px I think is related to default popup placement behavior
410-
_popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
411-
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
412-
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
422+
_popup.VerticalOffset = deltaY + 5;
413423
}
414424

415425
protected virtual void OnSelectedDateChanged(object sender, DatePickerSelectedValueChangedEventArgs e)

src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,9 @@ private void OnMonthChanged(object sender, EventArgs e)
534534

535535
internal double GetOffsetForPopup()
536536
{
537+
if (_monthSelector is null)
538+
return 0;
539+
537540
var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
538541
return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_monthSelector.ItemHeight / 2);
539542
}

src/Avalonia.Controls/DateTimePickers/TimePicker.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Avalonia.Controls.Shapes;
44
using Avalonia.Controls.Templates;
55
using Avalonia.Data;
6+
using Avalonia.Layout;
67
using System;
78
using System.Globalization;
89

@@ -254,16 +255,28 @@ protected virtual void OnSelectedTimeChanged(TimeSpan? oldTime, TimeSpan? newTim
254255

255256
private void OnFlyoutButtonClicked(object sender, Interactivity.RoutedEventArgs e)
256257
{
258+
if (_presenter == null)
259+
throw new InvalidOperationException("No DatePickerPresenter found.");
260+
if (_popup == null)
261+
throw new InvalidOperationException("No Popup found.");
262+
257263
_presenter.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
258264

265+
_popup.PlacementMode = PlacementMode.AnchorAndGravity;
266+
_popup.PlacementAnchor = Primitives.PopupPositioning.PopupAnchor.Bottom;
267+
_popup.PlacementGravity = Primitives.PopupPositioning.PopupGravity.Bottom;
268+
_popup.PlacementConstraintAdjustment = Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY;
259269
_popup.IsOpen = true;
260270

271+
// Overlay popup hosts won't get measured until the next layout pass, but we need the
272+
// template to be applied to `_presenter` now. Detect this case and force a layout pass.
273+
if (!_presenter.IsMeasureValid)
274+
(VisualRoot as ILayoutRoot)?.LayoutManager?.ExecuteInitialLayoutPass();
275+
261276
var deltaY = _presenter.GetOffsetForPopup();
262277

263278
// The extra 5 px I think is related to default popup placement behavior
264-
_popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
265-
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
266-
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
279+
_popup.VerticalOffset = deltaY + 5;
267280
}
268281

269282
private void OnDismissPicker(object sender, EventArgs e)

src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ private void OnSelectorButtonClick(object sender, RoutedEventArgs e)
253253

254254
internal double GetOffsetForPopup()
255255
{
256+
if (_hourSelector is null)
257+
return 0;
258+
256259
var acceptDismissButtonHeight = _acceptButton != null ? _acceptButton.Bounds.Height : 41;
257260
return -(MaxHeight - acceptDismissButtonHeight) / 2 - (_hourSelector.ItemHeight / 2);
258261
}

0 commit comments

Comments
 (0)