Skip to content

Commit e1f5b5a

Browse files
Adopt new SmartHint in ComboBox style (#3515)
* Initial work on adopting new SmartHint scheme in ComboBox style * Generate specific brush for ComboBox.OutlineBorder * Set correct default padding and brushes * Adorner rearrangement * Move trigger * Fix underline adorner * Add new ComboBox specific border brushes * Use new brushes in ComboBox style * Resource cleanup in ComboBox style * Delete redundant setter * Remove temporarily commented out elements/triggers * Split UI tests into pre- and post-SmartHint-refactor * Add condition in converter to maintain back-compat for clear button when IsEditable=False * Move wrongfully obsoleted brush to an alternate brush * Add newly required bindings for converters * Improve prefix suffix visibility for ComboBox * Fix prefix/suffix visibility in ComboBox * Add TextBox.IsReadOnly toggle to SmartHint demo page * Minor fixes to ComboBox style * Cleanup tests * Fix hint color when validation error is present * Adjustments after rebase * Always vertically center ComboBox ToggleButton chevron * Fix minor hint misalignment (rounding error) * Reset launchSettings.json back to default values * Add outline border tweak from TimePicker adoption as well
1 parent 6670a9c commit e1f5b5a

14 files changed

+506
-369
lines changed

MainDemo.Wpf/Domain/SmartHintViewModel.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ internal class SmartHintViewModel : ViewModelBase
3232
private bool _controlsEnabled = true;
3333
private bool _rippleOnFocus = false;
3434
private bool _textBoxAcceptsReturn = false;
35+
private bool _textBoxIsReadOnly = false;
3536
private int _maxLength;
3637
private PrefixSuffixVisibility _selectedPrefixVisibility = PrefixSuffixVisibility.WhenFocusedOrNonEmpty;
3738
private PrefixSuffixHintBehavior _selectedPrefixHintBehavior = PrefixSuffixHintBehavior.AlignWithPrefixSuffix;
@@ -202,6 +203,12 @@ public bool TextBoxAcceptsReturn
202203
set => SetProperty(ref _textBoxAcceptsReturn, value);
203204
}
204205

206+
public bool TextBoxIsReadOnly
207+
{
208+
get => _textBoxIsReadOnly;
209+
set => SetProperty(ref _textBoxIsReadOnly, value);
210+
}
211+
205212
public bool ShowCharacterCounter
206213
{
207214
get => MaxLength > 0;

MainDemo.Wpf/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"Demo App": {
44
"commandName": "Project",
5-
"commandLineArgs": "-p \"Smart Hint\" -t Inherit -f LeftToRight"
5+
"commandLineArgs": "-p Home -t Inherit -f LeftToRight"
66
}
77
}
88
}

MainDemo.Wpf/SmartHint.xaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,10 +359,13 @@
359359
<!-- TextBox variants -->
360360
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Text="TextBox styles" />
361361
<StackPanel Orientation="Horizontal">
362-
<CheckBox x:Name="TextBoxAcceptsReturnCheckBox"
363-
Content="AcceptsReturn"
362+
<CheckBox Content="AcceptsReturn"
364363
VerticalAlignment="Center"
365364
IsChecked="{Binding TextBoxAcceptsReturn}"/>
365+
<CheckBox Margin="30,0,0,0"
366+
Content="IsReadOnly"
367+
VerticalAlignment="Center"
368+
IsChecked="{Binding TextBoxIsReadOnly}"/>
366369
<TextBlock Margin="30,0,0,0"
367370
Text="H-ScrollBar visibility:"
368371
VerticalAlignment="Center" />
@@ -386,6 +389,7 @@
386389
<Grid.Resources>
387390
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource MaterialDesignFloatingHintTextBox}">
388391
<Setter Property="AcceptsReturn" Value="{Binding TextBoxAcceptsReturn}" />
392+
<Setter Property="IsReadOnly" Value="{Binding TextBoxIsReadOnly}" />
389393
<Setter Property="FontSize" Value="{Binding SelectedFontSize, Converter={StaticResource FontSizeConverter}}" />
390394
<Setter Property="Height" Value="{Binding SelectedCustomHeight}" />
391395
<Setter Property="Padding">
@@ -448,6 +452,7 @@
448452
<Grid.Resources>
449453
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource MaterialDesignFilledTextBox}">
450454
<Setter Property="AcceptsReturn" Value="{Binding TextBoxAcceptsReturn}" />
455+
<Setter Property="IsReadOnly" Value="{Binding TextBoxIsReadOnly}" />
451456
<Setter Property="FontSize" Value="{Binding SelectedFontSize, Converter={StaticResource FontSizeConverter}}" />
452457
<Setter Property="Height" Value="{Binding SelectedCustomHeight}" />
453458
<Setter Property="Padding">
@@ -511,6 +516,7 @@
511516
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource MaterialDesignOutlinedTextBox}">
512517
<Setter Property="AcceptsReturn" Value="{Binding TextBoxAcceptsReturn}" />
513518
<Setter Property="BorderThickness" Value="{Binding OutlineStyleBorderThickness}" />
519+
<Setter Property="IsReadOnly" Value="{Binding TextBoxIsReadOnly}" />
514520
<Setter Property="FontSize" Value="{Binding SelectedFontSize, Converter={StaticResource FontSizeConverter}}" />
515521
<Setter Property="Height" Value="{Binding SelectedCustomHeight}" />
516522
<Setter Property="Padding">

MaterialDesignThemes.UITests/WPF/TextFieldDefaultHeightTests.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ public async Task SameHeightWithDefaultStyle()
1515
var stackPanel = await LoadXaml<StackPanel>(@"
1616
<StackPanel>
1717
<PasswordBox />
18-
<ComboBox IsEditable=""True"" />
1918
<DatePicker />
2019
</StackPanel>");
2120

2221
var height = await GetHeight(stackPanel, "PasswordBox");
23-
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
2422
Assert.Equal(height, await GetHeight(stackPanel, "DatePicker"), Precision);
2523

2624
recorder.Success();
@@ -35,11 +33,12 @@ public async Task SameHeightWithDefaultStyle_PostSmartHintRefactor()
3533
var stackPanel = await LoadXaml<StackPanel>(@"
3634
<StackPanel>
3735
<TextBox />
36+
<ComboBox IsEditable=""True"" />
3837
<materialDesign:TimePicker />
3938
</StackPanel>");
4039

4140
var height = await GetHeight(stackPanel, "TextBox");
42-
//Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
41+
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
4342
Assert.Equal(height, await GetHeight(stackPanel, "TimePicker"), Precision);
4443

4544
recorder.Success();
@@ -54,13 +53,11 @@ public async Task SameHeightWithFloatingHintStyle()
5453
var stackPanel = await LoadXaml<StackPanel>(@"
5554
<StackPanel>
5655
<PasswordBox Style=""{StaticResource MaterialDesignFloatingHintPasswordBox}"" materialDesign:HintAssist.Hint=""Hint"" />
57-
<ComboBox IsEditable=""True"" Style=""{StaticResource MaterialDesignFloatingHintComboBox}"" materialDesign:HintAssist.Hint=""Hint"" />
5856
<DatePicker Style=""{StaticResource MaterialDesignFloatingHintDatePicker}"" materialDesign:HintAssist.Hint=""Hint"" />
5957
</StackPanel>");
6058

6159
var height = await GetHeight(stackPanel, "PasswordBox");
6260
Assert.True(height > 0);
63-
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
6461
Assert.Equal(height, await GetHeight(stackPanel, "DatePicker"), Precision);
6562

6663
recorder.Success();
@@ -75,12 +72,13 @@ public async Task SameHeightWithFloatingHintStyle_PostSmartHintRefactor()
7572
var stackPanel = await LoadXaml<StackPanel>(@"
7673
<StackPanel>
7774
<TextBox Style=""{StaticResource MaterialDesignFloatingHintTextBox}"" materialDesign:HintAssist.Hint=""Hint"" />
75+
<ComboBox IsEditable=""True"" Style=""{StaticResource MaterialDesignFloatingHintComboBox}"" materialDesign:HintAssist.Hint=""Hint"" />
7876
<materialDesign:TimePicker Style=""{StaticResource MaterialDesignFloatingHintTimePicker}"" materialDesign:HintAssist.Hint=""Hint"" />
7977
</StackPanel>");
8078

8179
var height = await GetHeight(stackPanel, "TextBox");
8280
Assert.True(height > 0);
83-
//Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
81+
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
8482
Assert.Equal(height, await GetHeight(stackPanel, "TimePicker"), Precision);
8583

8684
recorder.Success();
@@ -95,13 +93,11 @@ public async Task SameHeightWithFilledStyle()
9593
var stackPanel = await LoadXaml<StackPanel>(@"
9694
<StackPanel>
9795
<PasswordBox Style=""{StaticResource MaterialDesignFilledPasswordBox}"" materialDesign:HintAssist.Hint=""Hint"" />
98-
<ComboBox IsEditable=""True"" Style=""{StaticResource MaterialDesignFilledComboBox}"" materialDesign:HintAssist.Hint=""Hint"" />
9996
<DatePicker Style=""{StaticResource MaterialDesignFilledDatePicker}"" materialDesign:HintAssist.Hint=""Hint"" />
10097
</StackPanel>");
10198

10299
var height = await GetHeight(stackPanel, "PasswordBox");
103100
Assert.True(height > 0);
104-
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
105101
Assert.Equal(height, await GetHeight(stackPanel, "DatePicker"), Precision);
106102

107103
recorder.Success();
@@ -116,12 +112,13 @@ public async Task SameHeightWithFilledStyle_PostSmartHintRefactor()
116112
var stackPanel = await LoadXaml<StackPanel>(@"
117113
<StackPanel>
118114
<TextBox Style=""{StaticResource MaterialDesignFilledTextBox}"" materialDesign:HintAssist.Hint=""Hint"" />
115+
<ComboBox IsEditable=""True"" Style=""{StaticResource MaterialDesignFilledComboBox}"" materialDesign:HintAssist.Hint=""Hint"" />
119116
<materialDesign:TimePicker Style=""{StaticResource MaterialDesignFilledTimePicker}"" materialDesign:HintAssist.Hint=""Hint"" />
120117
</StackPanel>");
121118

122119
var height = await GetHeight(stackPanel, "TextBox");
123120
Assert.True(height > 0);
124-
//Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
121+
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
125122
Assert.Equal(height, await GetHeight(stackPanel, "TimePicker"), Precision);
126123

127124
recorder.Success();
@@ -136,13 +133,11 @@ public async Task SameHeightWithOutlinedStyle()
136133
var stackPanel = await LoadXaml<StackPanel>(@"
137134
<StackPanel>
138135
<PasswordBox Style=""{StaticResource MaterialDesignOutlinedPasswordBox}"" materialDesign:HintAssist.Hint=""Hint"" />
139-
<ComboBox IsEditable=""True"" Style=""{StaticResource MaterialDesignOutlinedComboBox}"" />
140136
<DatePicker Style=""{StaticResource MaterialDesignOutlinedDatePicker}"" materialDesign:HintAssist.Hint=""Hint"" />
141137
</StackPanel>");
142138

143139
var height = await GetHeight(stackPanel, "PasswordBox");
144140
Assert.True(height > 0);
145-
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
146141
Assert.Equal(height, await GetHeight(stackPanel, "DatePicker"), Precision);
147142

148143
recorder.Success();
@@ -157,12 +152,13 @@ public async Task SameHeightWithOutlinedStyle_PostSmartHintRefactor()
157152
var stackPanel = await LoadXaml<StackPanel>(@"
158153
<StackPanel>
159154
<TextBox Style=""{StaticResource MaterialDesignOutlinedTextBox}"" materialDesign:HintAssist.Hint=""Hint"" />
155+
<ComboBox IsEditable=""True"" Style=""{StaticResource MaterialDesignOutlinedComboBox}"" />
160156
<materialDesign:TimePicker Style=""{StaticResource MaterialDesignOutlinedTimePicker}"" materialDesign:HintAssist.Hint=""Hint"" />
161157
</StackPanel>");
162158

163159
var height = await GetHeight(stackPanel, "TextBox");
164160
Assert.True(height > 0);
165-
//Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
161+
Assert.Equal(height, await GetHeight(stackPanel, "ComboBox"), Precision);
166162
Assert.Equal(height, await GetHeight(stackPanel, "TimePicker"), Precision);
167163

168164
recorder.Success();

MaterialDesignThemes.UITests/WPF/Theme/ThemeTests.g.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ private partial string GetXamlWrapPanel()
5050
<TextBlock Text="ComboBox.FilledBackground" Background="{StaticResource MaterialDesign.Brush.ComboBox.FilledBackground}" />
5151
<TextBlock Text="ComboBox.HoverBackground" Background="{StaticResource MaterialDesign.Brush.ComboBox.HoverBackground}" />
5252
<TextBlock Text="ComboBox.OutlineInactiveBorder" Background="{StaticResource MaterialDesign.Brush.ComboBox.OutlineInactiveBorder}" />
53+
<TextBlock Text="ComboBox.HoverBorder" Background="{StaticResource MaterialDesign.Brush.ComboBox.HoverBorder}" />
54+
<TextBlock Text="ComboBox.Border" Background="{StaticResource MaterialDesign.Brush.ComboBox.Border}" />
55+
<TextBlock Text="ComboBox.OutlineBorder" Background="{StaticResource MaterialDesign.Brush.ComboBox.OutlineBorder}" />
5356
<TextBlock Text="ComboBox.Popup.DarkBackground" Background="{StaticResource MaterialDesign.Brush.ComboBox.Popup.DarkBackground}" />
5457
<TextBlock Text="ComboBox.Popup.DarkForeground" Background="{StaticResource MaterialDesign.Brush.ComboBox.Popup.DarkForeground}" />
5558
<TextBlock Text="ComboBox.Popup.LightBackground" Background="{StaticResource MaterialDesign.Brush.ComboBox.Popup.LightBackground}" />
@@ -119,6 +122,12 @@ private partial string GetXamlWrapPanel()
119122
<TextBlock Text="MaterialDesignCheckBoxOff" Background="{StaticResource MaterialDesignCheckBoxOff}" />
120123
<TextBlock Text="MaterialDesignTextBoxBorder" Background="{StaticResource MaterialDesignTextBoxBorder}" />
121124
<TextBlock Text="MaterialDesignChipBackground" Background="{StaticResource MaterialDesignChipBackground}" />
125+
<TextBlock Text="MaterialDesignBody" Background="{StaticResource MaterialDesignBody}" />
126+
<TextBlock Text="MaterialDesignBodyLight" Background="{StaticResource MaterialDesignBodyLight}" />
127+
<TextBlock Text="MaterialDesignCheckBoxOff" Background="{StaticResource MaterialDesignCheckBoxOff}" />
128+
<TextBlock Text="MaterialDesignTextBoxBorder" Background="{StaticResource MaterialDesignTextBoxBorder}" />
129+
<TextBlock Text="MaterialDesignColumnHeader" Background="{StaticResource MaterialDesignColumnHeader}" />
130+
<TextBlock Text="MaterialDesignTextAreaBorder" Background="{StaticResource MaterialDesignTextAreaBorder}" />
122131
<TextBlock Text="MaterialDesignDataGridRowHoverBackground" Background="{StaticResource MaterialDesignDataGridRowHoverBackground}" />
123132
<TextBlock Text="MaterialDesignColumnHeader" Background="{StaticResource MaterialDesignColumnHeader}" />
124133
<TextBlock Text="MaterialDesignTextAreaBorder" Background="{StaticResource MaterialDesignTextAreaBorder}" />
@@ -303,6 +312,21 @@ private partial async Task AssertAllThemeBrushesSet(IVisualElement<WrapPanel> pa
303312
Color? textBlockBackground = await textBlock.GetBackgroundColor();
304313
Assert.Equal(await GetResourceColor("MaterialDesign.Brush.ComboBox.OutlineInactiveBorder"), textBlockBackground);
305314
}
315+
{
316+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"ComboBox.HoverBorder\"]");
317+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
318+
Assert.Equal(await GetResourceColor("MaterialDesign.Brush.ComboBox.HoverBorder"), textBlockBackground);
319+
}
320+
{
321+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"ComboBox.Border\"]");
322+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
323+
Assert.Equal(await GetResourceColor("MaterialDesign.Brush.ComboBox.Border"), textBlockBackground);
324+
}
325+
{
326+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"ComboBox.OutlineBorder\"]");
327+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
328+
Assert.Equal(await GetResourceColor("MaterialDesign.Brush.ComboBox.OutlineBorder"), textBlockBackground);
329+
}
306330
{
307331
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"ComboBox.Popup.DarkBackground\"]");
308332
Color? textBlockBackground = await textBlock.GetBackgroundColor();
@@ -648,6 +672,36 @@ private partial async Task AssertAllThemeBrushesSet(IVisualElement<WrapPanel> pa
648672
Color? textBlockBackground = await textBlock.GetBackgroundColor();
649673
Assert.Equal(await GetResourceColor("MaterialDesignChipBackground"), textBlockBackground);
650674
}
675+
{
676+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignBody\"]");
677+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
678+
Assert.Equal(await GetResourceColor("MaterialDesignBody"), textBlockBackground);
679+
}
680+
{
681+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignBodyLight\"]");
682+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
683+
Assert.Equal(await GetResourceColor("MaterialDesignBodyLight"), textBlockBackground);
684+
}
685+
{
686+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignCheckBoxOff\"]");
687+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
688+
Assert.Equal(await GetResourceColor("MaterialDesignCheckBoxOff"), textBlockBackground);
689+
}
690+
{
691+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignTextBoxBorder\"]");
692+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
693+
Assert.Equal(await GetResourceColor("MaterialDesignTextBoxBorder"), textBlockBackground);
694+
}
695+
{
696+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignColumnHeader\"]");
697+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
698+
Assert.Equal(await GetResourceColor("MaterialDesignColumnHeader"), textBlockBackground);
699+
}
700+
{
701+
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignTextAreaBorder\"]");
702+
Color? textBlockBackground = await textBlock.GetBackgroundColor();
703+
Assert.Equal(await GetResourceColor("MaterialDesignTextAreaBorder"), textBlockBackground);
704+
}
651705
{
652706
IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"MaterialDesignDataGridRowHoverBackground\"]");
653707
Color? textBlockBackground = await textBlock.GetBackgroundColor();
@@ -790,6 +844,9 @@ private static IEnumerable<string> GetBrushResourceNames()
790844
yield return "MaterialDesign.Brush.ComboBox.FilledBackground";
791845
yield return "MaterialDesign.Brush.ComboBox.HoverBackground";
792846
yield return "MaterialDesign.Brush.ComboBox.OutlineInactiveBorder";
847+
yield return "MaterialDesign.Brush.ComboBox.HoverBorder";
848+
yield return "MaterialDesign.Brush.ComboBox.Border";
849+
yield return "MaterialDesign.Brush.ComboBox.OutlineBorder";
793850
yield return "MaterialDesign.Brush.ComboBox.Popup.DarkBackground";
794851
yield return "MaterialDesign.Brush.ComboBox.Popup.DarkForeground";
795852
yield return "MaterialDesign.Brush.ComboBox.Popup.LightBackground";
@@ -862,6 +919,12 @@ private static IEnumerable<string> GetObsoleteBrushResourceNames()
862919
yield return "MaterialDesignCheckBoxOff";
863920
yield return "MaterialDesignTextBoxBorder";
864921
yield return "MaterialDesignChipBackground";
922+
yield return "MaterialDesignBody";
923+
yield return "MaterialDesignBodyLight";
924+
yield return "MaterialDesignCheckBoxOff";
925+
yield return "MaterialDesignTextBoxBorder";
926+
yield return "MaterialDesignColumnHeader";
927+
yield return "MaterialDesignTextAreaBorder";
865928
yield return "MaterialDesignDataGridRowHoverBackground";
866929
yield return "MaterialDesignColumnHeader";
867930
yield return "MaterialDesignTextAreaBorder";

MaterialDesignThemes.Wpf/Converters/ComboBoxClearButtonMarginConverter.cs

Lines changed: 0 additions & 21 deletions
This file was deleted.

MaterialDesignThemes.Wpf/Converters/TextFieldClearButtonVisibilityConverter.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,22 @@ internal class TextFieldClearButtonVisibilityConverter : IMultiValueConverter
99

1010
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
1111
{
12-
if (!(bool)values[0]) // TextFieldAssist.HasClearButton
12+
if (values is not [bool hasClearButton, bool isContentNullOrEmpty, ..])
13+
{
14+
return Visibility.Visible;
15+
}
16+
17+
if (!hasClearButton) // TextFieldAssist.HasClearButton
18+
{
19+
return Visibility.Collapsed;
20+
}
21+
22+
if (isContentNullOrEmpty && values.Length > 2 && values[2] is false) // ComboBox.IsEditable
23+
{
1324
return Visibility.Collapsed;
25+
}
1426

15-
return (bool)values[1] // Hint.IsContentNullOrEmpty
27+
return isContentNullOrEmpty // Hint.IsContentNullOrEmpty
1628
? ContentEmptyVisibility
1729
: Visibility.Visible;
1830
}

0 commit comments

Comments
 (0)