-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Refactor PopupBox placement to respect configurable elevation #3136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
b1777ed
Add failing UI test
nicolaihenriksen dbe3a64
Fix Card clipping issue
nicolaihenriksen d995ab6
Refactor PopupBox custom popup placement
nicolaihenriksen 0dd2e87
Add dedicated demo app page for PopupBox
nicolaihenriksen cc4bf65
Small cleanup done during review on stream
Keboo d45e5b9
Change implementation to dedicated DP
nicolaihenriksen 1988f83
Fix PopupTest to use new dedicated DP
nicolaihenriksen f462017
Moving converters inside of the tempalate
Keboo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,208 @@ | ||
| <UserControl x:Class="MaterialDesignDemo.PopupBox" | ||
| xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
| xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
| xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
| xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
| xmlns:local="clr-namespace:MaterialDesignDemo" | ||
| xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" | ||
| xmlns:system="clr-namespace:System;assembly=System.Runtime" | ||
| mc:Ignorable="d" | ||
| d:DesignHeight="450" d:DesignWidth="800"> | ||
| <UserControl.Resources> | ||
| <ResourceDictionary> | ||
| <!-- This is needed to avoid runtime exceptions?! Seems like this might be a bug? --> | ||
| <ResourceDictionary.MergedDictionaries> | ||
| <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.PopupBox.xaml" /> | ||
| </ResourceDictionary.MergedDictionaries> | ||
|
|
||
| <DataTemplate x:Key="ContentTemplateGrid"> | ||
| <Grid Width="200" Height="100" TextElement.Foreground="{DynamicResource MaterialDesignLightForeground}"> | ||
| <TextBlock Text="Popup content in grid" HorizontalAlignment="Center" VerticalAlignment="Center" /> | ||
| </Grid> | ||
| </DataTemplate> | ||
|
|
||
| <DataTemplate x:Key="ContentTemplateGridWithBackground"> | ||
| <Grid Width="200" Height="100" Background="Fuchsia"> | ||
| <TextBlock Text="Popup content in colored grid" HorizontalAlignment="Center" VerticalAlignment="Center" /> | ||
| </Grid> | ||
| </DataTemplate> | ||
|
|
||
| <DataTemplate x:Key="ContentTemplateButtonStack"> | ||
| <!-- Margin of 10 here is to "make room" for the elevation drop shadows of the buttons. Must be compensated for in some (left/right) alignment scenarios using PopupBox.PopupHorizontalOffset --> | ||
| <StackPanel Margin="10"> | ||
| <Button Content="1" | ||
| Opacity="0.5" | ||
| ToolTip="One with custom opacity" /> | ||
| <Button Content="2" ToolTip="Two" /> | ||
| <Button Content="3" ToolTip="Three" /> | ||
| </StackPanel> | ||
Keboo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </DataTemplate> | ||
|
|
||
| <DataTemplate x:Key="ContentTemplateButtonStackWithBackground"> | ||
| <Grid Background="Fuchsia"> | ||
| <StackPanel Margin="10"> | ||
| <Button Content="1" | ||
| Opacity="0.5" | ||
| ToolTip="One with custom opacity" /> | ||
| <Button Content="2" ToolTip="Two" /> | ||
| <Button Content="3" ToolTip="Three" /> | ||
| </StackPanel> | ||
| </Grid> | ||
| </DataTemplate> | ||
|
|
||
| <x:Array x:Key="{x:Static local:PopupBox.DefaultStyleContentKey}" Type="ComboBoxItem"> | ||
| <ComboBoxItem Tag="{StaticResource ContentTemplateGrid}" materialDesign:HintAssist.HelperText="Selected content works best when used with the MaterialDesignPopupBox style">Grid</ComboBoxItem> | ||
| <ComboBoxItem Tag="{StaticResource ContentTemplateGridWithBackground}">Colored grid</ComboBoxItem> | ||
| </x:Array> | ||
|
|
||
| <x:Array x:Key="{x:Static local:PopupBox.MultiFloatingActionStyleContentKey}" Type="ComboBoxItem"> | ||
| <ComboBoxItem Tag="{StaticResource ContentTemplateButtonStack}" materialDesign:HintAssist.HelperText="Margin in the selected content (stack of buttons) needs to be compensated for in certain alignments (left/right)">Stack of buttons</ComboBoxItem> | ||
| <ComboBoxItem Tag="{StaticResource ContentTemplateButtonStackWithBackground}">Stack of buttons in colored grid</ComboBoxItem> | ||
| </x:Array> | ||
|
|
||
| <local:ComboBoxItemToDataTemplateConverter x:Key="ComboBoxItemToDataTemplateConverter" /> | ||
| <local:ComboBoxItemToStyleConverter x:Key="ComboBoxItemToStyleConverter" /> | ||
| <local:ComboBoxItemToHelperTextConverter x:Key="ComboBoxItemToHelperTextConverter" /> | ||
|
|
||
| <Thickness x:Key="Spacer">0,30,0,0</Thickness> | ||
| </ResourceDictionary> | ||
| </UserControl.Resources> | ||
| <Grid> | ||
| <Grid.ColumnDefinitions> | ||
| <ColumnDefinition Width="*" /> | ||
| <ColumnDefinition Width="250" /> | ||
| </Grid.ColumnDefinitions> | ||
|
|
||
| <Grid Grid.Column="0"> | ||
| <Grid.RowDefinitions> | ||
| <RowDefinition Height="Auto" /> | ||
| <RowDefinition Height="*" /> | ||
| </Grid.RowDefinitions> | ||
|
|
||
| <TextBlock Grid.Row="0" HorizontalAlignment="Center" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" | ||
| Text="{Binding ElementName=ContentComboBox, Path=SelectedItem, Converter={StaticResource ComboBoxItemToHelperTextConverter}}" /> | ||
|
|
||
| <materialDesign:PopupBox Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Center" SnapsToDevicePixels="True" Padding="0" | ||
| Style="{Binding ElementName=StyleComboBox, Path=SelectedItem, Converter={StaticResource ComboBoxItemToStyleConverter}}" | ||
| PopupElevation="{Binding ElementName=ElevationComboBox, Path=SelectedItem}" | ||
| PopupUniformCornerRadius="{Binding ElementName=UniformCornerRadiusComboBox, Path=SelectedItem}" | ||
| PopupHorizontalOffset="{Binding ElementName=HorizontalOffsetComboBox, Path=SelectedItem}" | ||
| PopupVerticalOffset="{Binding ElementName=VerticalOffsetComboBox, Path=SelectedItem}" | ||
| PlacementMode="{Binding ElementName=PopupBoxPlacementModeComboBox, Path=SelectedItem}"> | ||
| <ContentControl ContentTemplate="{Binding ElementName=ContentComboBox, Path=SelectedItem, Converter={StaticResource ComboBoxItemToDataTemplateConverter}}" /> | ||
| </materialDesign:PopupBox> | ||
| </Grid> | ||
|
|
||
| <StackPanel Grid.Column="1" Orientation="Vertical"> | ||
| <GroupBox Header="Properties" Padding="10"> | ||
| <StackPanel Orientation="Vertical"> | ||
| <TextBlock Text="Style:" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="StyleComboBox" SelectionChanged="StyleComboBox_OnSelectionChanged"> | ||
| <ComboBoxItem Tag="{StaticResource MaterialDesignPopupBox}">MaterialDesignPopupBox</ComboBoxItem> | ||
| <ComboBoxItem Tag="{StaticResource MaterialDesignMultiFloatingActionPopupBox}">MaterialDesignMultiFloatingActionPopupBox</ComboBoxItem> | ||
| </ComboBox> | ||
|
|
||
| <TextBlock Text="Elevation:" Margin="{StaticResource Spacer}" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="ElevationComboBox" SelectedIndex="6"> | ||
| <materialDesign:Elevation>Dp0</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp1</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp2</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp3</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp4</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp5</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp6</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp7</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp8</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp12</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp16</materialDesign:Elevation> | ||
| <materialDesign:Elevation>Dp24</materialDesign:Elevation> | ||
| </ComboBox> | ||
|
|
||
| <TextBlock Text="PopupUniformCornerRadius:" Margin="{StaticResource Spacer}" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="UniformCornerRadiusComboBox" SelectedIndex="2"> | ||
| <system:Double>0</system:Double> | ||
| <system:Double>2</system:Double> | ||
| <system:Double>4</system:Double> | ||
| <system:Double>6</system:Double> | ||
| <system:Double>8</system:Double> | ||
| <system:Double>10</system:Double> | ||
| <system:Double>20</system:Double> | ||
| </ComboBox> | ||
|
|
||
| <TextBlock Text="PopupHorizontalOffset:" Margin="{StaticResource Spacer}" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="HorizontalOffsetComboBox" SelectedIndex="10"> | ||
| <system:Double>-100</system:Double> | ||
| <system:Double>-50</system:Double> | ||
| <system:Double>-20</system:Double> | ||
| <system:Double>-15</system:Double> | ||
| <system:Double>-10</system:Double> | ||
| <system:Double>-5</system:Double> | ||
| <system:Double>-4</system:Double> | ||
| <system:Double>-3</system:Double> | ||
| <system:Double>-2</system:Double> | ||
| <system:Double>-1</system:Double> | ||
| <system:Double>0</system:Double> | ||
| <system:Double>1</system:Double> | ||
| <system:Double>2</system:Double> | ||
| <system:Double>3</system:Double> | ||
| <system:Double>4</system:Double> | ||
| <system:Double>5</system:Double> | ||
| <system:Double>10</system:Double> | ||
| <system:Double>15</system:Double> | ||
| <system:Double>20</system:Double> | ||
| <system:Double>50</system:Double> | ||
| <system:Double>100</system:Double> | ||
| </ComboBox> | ||
|
|
||
| <TextBlock Text="PopupVerticalOffset:" Margin="{StaticResource Spacer}" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="VerticalOffsetComboBox" SelectedIndex="10"> | ||
| <system:Double>-100</system:Double> | ||
| <system:Double>-50</system:Double> | ||
| <system:Double>-20</system:Double> | ||
| <system:Double>-15</system:Double> | ||
| <system:Double>-10</system:Double> | ||
| <system:Double>-5</system:Double> | ||
| <system:Double>-4</system:Double> | ||
| <system:Double>-3</system:Double> | ||
| <system:Double>-2</system:Double> | ||
| <system:Double>-1</system:Double> | ||
| <system:Double>0</system:Double> | ||
| <system:Double>1</system:Double> | ||
| <system:Double>2</system:Double> | ||
| <system:Double>3</system:Double> | ||
| <system:Double>4</system:Double> | ||
| <system:Double>5</system:Double> | ||
| <system:Double>10</system:Double> | ||
| <system:Double>15</system:Double> | ||
| <system:Double>20</system:Double> | ||
| <system:Double>50</system:Double> | ||
| <system:Double>100</system:Double> | ||
| </ComboBox> | ||
|
|
||
| <TextBlock Text="PopupBoxPlacementMode:" Margin="{StaticResource Spacer}" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="PopupBoxPlacementModeComboBox" SelectedIndex="1"> | ||
| <materialDesign:PopupBoxPlacementMode>BottomAndAlignCentres</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>BottomAndAlignLeftEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>BottomAndAlignRightEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>LeftAndAlignBottomEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>LeftAndAlignMiddles</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>LeftAndAlignTopEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>RightAndAlignBottomEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>RightAndAlignMiddles</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>RightAndAlignTopEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>TopAndAlignCentres</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>TopAndAlignLeftEdges</materialDesign:PopupBoxPlacementMode> | ||
| <materialDesign:PopupBoxPlacementMode>TopAndAlignRightEdges</materialDesign:PopupBoxPlacementMode> | ||
| </ComboBox> | ||
| </StackPanel> | ||
| </GroupBox> | ||
|
|
||
| <GroupBox Header="Popup" Margin="{StaticResource Spacer}" Padding="10"> | ||
| <StackPanel Orientation="Vertical"> | ||
| <TextBlock Text="Popup Content:" Style="{StaticResource MaterialDesignSubtitle2TextBlock}" /> | ||
| <ComboBox x:Name="ContentComboBox" /> | ||
| </StackPanel> | ||
| </GroupBox> | ||
| </StackPanel> | ||
| </Grid> | ||
| </UserControl> | ||
This file contains hidden or 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,69 @@ | ||
| using System.Collections; | ||
| using System.Globalization; | ||
| using System.Windows.Data; | ||
| using MaterialDesignThemes.Wpf; | ||
|
|
||
| namespace MaterialDesignDemo; | ||
|
|
||
| /// <summary> | ||
| /// Interaction logic for PopupBox.xaml | ||
| /// </summary> | ||
| public partial class PopupBox : UserControl | ||
| { | ||
| public const string DefaultStyleContentKey = nameof(DefaultStyleContentKey); | ||
| public const string MultiFloatingActionStyleContentKey = nameof(MultiFloatingActionStyleContentKey); | ||
|
|
||
| private readonly IEnumerable _defaultStyleContent; | ||
| private readonly IEnumerable _multiFloatingActionStyleContentKey; | ||
|
|
||
| public PopupBox() | ||
| { | ||
| InitializeComponent(); | ||
|
|
||
| _defaultStyleContent = (IEnumerable)FindResource(DefaultStyleContentKey); | ||
| _multiFloatingActionStyleContentKey = (IEnumerable)FindResource(MultiFloatingActionStyleContentKey); | ||
|
|
||
| Loaded += (sender, args) => StyleComboBox.SelectedIndex = 0; | ||
| } | ||
|
|
||
| private void StyleComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) | ||
| { | ||
| ComboBoxItem selectedItem = (ComboBoxItem) StyleComboBox.SelectedItem; | ||
| if (Equals(selectedItem.Content, "MaterialDesignPopupBox")) | ||
| { | ||
| ContentComboBox.ItemsSource = _defaultStyleContent; | ||
| } | ||
| else | ||
| { | ||
| ContentComboBox.ItemsSource = _multiFloatingActionStyleContentKey; | ||
| } | ||
| ContentComboBox.SelectedIndex = 0; | ||
| } | ||
| } | ||
|
|
||
| internal class ComboBoxItemToDataTemplateConverter : IValueConverter | ||
| { | ||
| public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| => value is ComboBoxItem { Tag: DataTemplate template} ? template : null; | ||
|
|
||
| public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| => throw new NotImplementedException(); | ||
| } | ||
|
|
||
| internal class ComboBoxItemToStyleConverter : IValueConverter | ||
| { | ||
| public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| => value is ComboBoxItem { Tag: Style style } ? style : null; | ||
|
|
||
| public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| => throw new NotImplementedException(); | ||
| } | ||
|
|
||
| internal class ComboBoxItemToHelperTextConverter : IValueConverter | ||
| { | ||
| public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| => value is ComboBoxItem item ? HintAssist.GetHelperText(item) : null!; | ||
|
|
||
| public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| => throw new NotImplementedException(); | ||
| } |
37 changes: 37 additions & 0 deletions
37
MaterialDesignThemes.UITests/WPF/PopupBox/PopupBoxTests.cs
This file contains hidden or 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,37 @@ | ||
| using System.ComponentModel; | ||
|
|
||
| namespace MaterialDesignThemes.UITests.WPF.PopupBox; | ||
|
|
||
| public class PopupBoxTests : TestBase | ||
| { | ||
| public PopupBoxTests(ITestOutputHelper output) | ||
| : base(output) | ||
| { } | ||
|
|
||
| [Theory] | ||
| [InlineData(Elevation.Dp0)] | ||
| [InlineData(Elevation.Dp16)] | ||
| [InlineData(Elevation.Dp24)] | ||
| [Description("Issue 3129")] | ||
| public async Task PopupBox_WithElevation_AppliesElevationToNestedCard(Elevation elevation) | ||
| { | ||
| await using var recorder = new TestRecorder(App); | ||
|
|
||
| //Arrange | ||
| IVisualElement<Wpf.PopupBox> popupBox = await LoadXaml<Wpf.PopupBox>($@" | ||
| <materialDesign:PopupBox VerticalAlignment=""Top"" | ||
| PopupElevation=""{elevation}""> | ||
| <StackPanel> | ||
| <Button Content=""More"" /> | ||
| <Button Content=""Options"" /> | ||
| </StackPanel> | ||
| </materialDesign:PopupBox>"); | ||
|
|
||
| IVisualElement<Card> card = await popupBox.GetElement<Card>("/Card"); | ||
|
|
||
| // Assert | ||
| Assert.Equal(elevation, await card.GetProperty<Elevation?>(ElevationAssist.ElevationProperty)); | ||
|
|
||
| recorder.Success(); | ||
| } | ||
| } |
This file contains hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.