Skip to content

Commit d84b6c7

Browse files
committed
improved combobox alignment approach
1 parent 6a92ce0 commit d84b6c7

File tree

1 file changed

+19
-36
lines changed

1 file changed

+19
-36
lines changed

source/iNKORE.UI.WPF.Modern/Controls/Helpers/WinUIComboBoxBehaviorHelper.cs

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Windows.Controls.Primitives;
66
using System.Windows.Input;
77
using iNKORE.UI.WPF.Converters;
8+
using iNKORE.UI.WPF.Modern.Controls.Primitives;
89

910
namespace iNKORE.UI.WPF.Modern.Controls.Helpers
1011
{
@@ -92,56 +93,38 @@ private static void OnDropDownOpened(object sender, object args)
9293

9394
private static void AlignSelectedContainer(ComboBox comboBox, Popup popup)
9495
{
95-
if (comboBox.IsEditable)
96+
if (comboBox.IsEditable || comboBox.ItemContainerGenerator.Items.Count < 1)
9697
{
9798
popup.VerticalOffset = 0;
9899
return;
99100
}
100101

101-
if (GetToAlignContainer(comboBox) is not { } itemContainer ||
102-
itemContainer.TranslatePoint(new Point(0, -itemContainer.ActualHeight + itemContainer.Padding.Top + comboBox.Padding.Top),
103-
comboBox) is not { Y: not 0 } itemTop)
104-
{
105-
return;
106-
}
107-
108-
while (itemTop.Y is not 0)
102+
var mockContainer = (comboBox.ItemContainerGenerator.ContainerFromIndex(0) as ComboBoxItem)!;
103+
var scrollViewer = GetTemplateChild<ScrollViewer>("ScrollViewer", comboBox);
104+
105+
var toSelectIndex = comboBox.SelectedIndex;
106+
if (toSelectIndex < 0)
109107
{
110-
var preY = itemTop.Y;
111-
popup.VerticalOffset -= preY;
112-
itemTop = itemContainer.TranslatePoint(new Point(0, -itemContainer.ActualHeight + comboBox.Padding.Top),
113-
comboBox);
114-
115-
var postY = itemTop.Y;
116-
117-
if (postY >= preY)
118-
{
119-
//if this loop didn't bring the popup top closer, then this mean the popup couldn't position itself.
120-
break;
121-
}
108+
toSelectIndex = (int)Math.Ceiling(comboBox.Items.Count / 2.0);
109+
TryHighlightingFirstItem(comboBox);
122110
}
123-
124-
if (itemContainer.ActualHeight - comboBox.ActualHeight > 0)
111+
else if (mockContainer.ActualHeight * comboBox.Items.Count > comboBox.MaxDropDownHeight)
125112
{
126-
popup.VerticalOffset -= comboBox.ActualHeight;
113+
toSelectIndex = 0;
127114
}
128-
}
115+
116+
var paddingBorder = (scrollViewer.Parent as Border)!;
129117

130-
private static ComboBoxItem GetToAlignContainer(ComboBox comboBox)
131-
{
132-
DependencyObject container;
133-
if (comboBox.SelectedItem is null)
118+
if (IsPopupOpenDown(comboBox, popup.VerticalOffset))
134119
{
135-
container = comboBox.ItemContainerGenerator.ContainerFromIndex(
136-
(int)Math.Ceiling(comboBox.Items.Count / 2.0));
137-
TryHighlightingFirstItem(comboBox);
120+
popup.VerticalOffset = -mockContainer.ActualHeight * (toSelectIndex + 1) - paddingBorder.Padding.Top;
138121
}
139122
else
140123
{
141-
container = comboBox.ItemContainerGenerator.ContainerFromItem(comboBox.SelectedItem);
124+
popup.VerticalOffset =
125+
mockContainer.ActualHeight * (Math.Min((int)(comboBox.MaxDropDownHeight / mockContainer.ActualHeight), comboBox.Items.Count) - toSelectIndex) +
126+
paddingBorder.Padding.Bottom;
142127
}
143-
144-
return container as ComboBoxItem;
145128
}
146129

147130
private static void TryHighlightingFirstItem(ComboBox comboBox)
@@ -221,7 +204,7 @@ private static bool IsPopupOpenDown(ComboBox comboBox, double popupVerticalOffse
221204

222205
var popupTopPoint = popupBorder.TranslatePoint(new Point(0, 0), textBox);
223206

224-
return popupTopPoint.Y + popupVerticalOffset > 0;
207+
return popupTopPoint.Y > popupVerticalOffset;
225208
}
226209

227210
private static object ResourceLookup(Control control, object key)

0 commit comments

Comments
 (0)