-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add option for custom popup placement for ComboBox (#3005)
* Add special ComboBox popup handling for 90 degrees rotation Popup placement was wrong in case a LayoutTransform was applied to rotate the ComboBox. The default WPF ComboBox does respect this, and thus so should MDIX. To RotateTransfrom.Angle is compared against values of 90 and -90 (10 digit precision) to determine whether this is a rotation where the special handling should be applied. * Refactor custom popup placement into publicly exposed callback Rather than handling arbitrary rotations in the library itself, we expose a callback which can then be used to rotate the popup shown by the combobox such that it matches the users needs. * Update MaterialDesignThemes.Wpf/ComboBoxPopup.cs Co-authored-by: Kevin B <[email protected]> * Fix compile error Co-authored-by: Kevin B <[email protected]>
- Loading branch information
1 parent
4c4a754
commit 11b6757
Showing
7 changed files
with
276 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,60 @@ | ||
using MaterialDesignDemo.Domain; | ||
using Screen = System.Windows.Forms.Screen; | ||
using DrawingPoint = System.Drawing.Point; | ||
|
||
namespace MaterialDesignDemo | ||
namespace MaterialDesignDemo; | ||
|
||
public partial class ComboBoxes | ||
{ | ||
public partial class ComboBoxes | ||
private const double DropShadowHeight = 6; // This does not account for DPI scaling! | ||
|
||
public static CustomPopupPlacementCallback Rotate90DegreesClockWiseCallback { get; } = (popupSize, targetSize, offset) => | ||
{ | ||
public ComboBoxes() | ||
// ComboBox is rotated 90 degrees clockwise (ie. Left=Up, Right=Down) | ||
var comboBox = VisualTreeUtil.GetElementUnderMouse<ComboBox>(); | ||
var comboBoxLocation = comboBox.PointToScreen(new Point(0, 0)); | ||
Screen screen = Screen.FromPoint(new DrawingPoint((int)comboBoxLocation.X, (int)comboBoxLocation.Y)); | ||
int comboBoxOffsetX = (int)(comboBoxLocation.X - screen.Bounds.X) % screen.Bounds.Width; | ||
double y = offset.Y - DropShadowHeight; | ||
double x = offset.X; | ||
double rotatedComboBoxHeight = targetSize.Width; | ||
if (comboBoxOffsetX + x > popupSize.Width + rotatedComboBoxHeight) | ||
{ | ||
InitializeComponent(); | ||
DataContext = new ComboBoxesViewModel(); | ||
x -= popupSize.Width + rotatedComboBoxHeight; | ||
} | ||
return new[] { new CustomPopupPlacement(new Point(x, y), PopupPrimaryAxis.Horizontal) }; | ||
}; | ||
|
||
private void ClearFilledComboBox_Click(object sender, System.Windows.RoutedEventArgs e) | ||
=> FilledComboBox.SelectedItem = null; | ||
public static CustomPopupPlacementCallback Rotate90DegreesCounterClockWiseCallback { get; } = (popupSize, targetSize, offset) => | ||
{ | ||
// ComboBox is rotated 90 degrees counter-clockwise (ie. Left=Down, Right=Up) | ||
var comboBox = VisualTreeUtil.GetElementUnderMouse<ComboBox>(); | ||
var comboBoxLocation = comboBox.PointToScreen(new Point(0, 0)); | ||
Screen screen = Screen.FromPoint(new DrawingPoint((int)comboBoxLocation.X, (int)comboBoxLocation.Y)); | ||
int comboBoxOffsetX = (int)(comboBoxLocation.X - screen.Bounds.X) % screen.Bounds.Width; | ||
double y = offset.Y - popupSize.Height + DropShadowHeight; | ||
double x = offset.X; | ||
double rotatedComboBoxHeight = targetSize.Width; | ||
if (comboBoxOffsetX + x + rotatedComboBoxHeight + popupSize.Width > screen.Bounds.Width) | ||
{ | ||
x -= popupSize.Width; | ||
} | ||
else | ||
{ | ||
x += rotatedComboBoxHeight; | ||
} | ||
return new[] { new CustomPopupPlacement(new Point(x, y), PopupPrimaryAxis.Horizontal) }; | ||
}; | ||
|
||
private void ClearOutlinedComboBox_Click(object sender, System.Windows.RoutedEventArgs e) | ||
=> OutlinedComboBox.SelectedItem = null; | ||
public ComboBoxes() | ||
{ | ||
InitializeComponent(); | ||
DataContext = new ComboBoxesViewModel(); | ||
} | ||
|
||
private void ClearFilledComboBox_Click(object sender, System.Windows.RoutedEventArgs e) | ||
=> FilledComboBox.SelectedItem = null; | ||
|
||
private void ClearOutlinedComboBox_Click(object sender, System.Windows.RoutedEventArgs e) | ||
=> OutlinedComboBox.SelectedItem = null; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System.Globalization; | ||
using System.Windows.Data; | ||
|
||
namespace MaterialDesignDemo.Converters; | ||
|
||
public class BooleanToDoubleConverter : MarkupExtension, IValueConverter | ||
{ | ||
public double TrueValue { get; set; } | ||
public double FalseValue { get; set; } | ||
|
||
public override object ProvideValue(IServiceProvider serviceProvider) => this; | ||
|
||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => value is true ? TrueValue : FalseValue; | ||
|
||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using System.Windows.Media; | ||
|
||
namespace MaterialDesignDemo; | ||
|
||
internal static class VisualTreeUtil | ||
{ | ||
private static T FindVisualParent<T>(UIElement element) where T : UIElement? | ||
{ | ||
UIElement? parent = element; | ||
while (parent != null) | ||
{ | ||
if (parent is T correctlyTyped) | ||
{ | ||
return correctlyTyped; | ||
} | ||
parent = VisualTreeHelper.GetParent(parent) as UIElement; | ||
} | ||
return default!; | ||
} | ||
|
||
internal static T GetElementUnderMouse<T>() where T : UIElement? => FindVisualParent<T>((Mouse.DirectlyOver as UIElement)!); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters