Skip to content

Commit 3581555

Browse files
committed
Merge branch 'feature/win11theming/staging' of https://github.com/dotnet/wpf into ComboBox
2 parents cc7cad0 + 13a597c commit 3581555

31 files changed

+1766
-492
lines changed

src/Microsoft.DotNet.Wpf/ApiCompat/Baselines/PresentationFramework-ref.baseline.txt

+40-1
Large diffs are not rendered by default.

src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj

+9
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@
417417
<Compile Include="System\Windows\Appearance\WindowBackgroundManager.cs" />
418418
<Compile Include="System\Windows\Appearance\WindowBackdrop.cs" />
419419
<Compile Include="System\Windows\Controls\FallbackBrushConverter.cs" />
420+
<Compile Include="System\Windows\Controls\ElementPlacement.cs" />
421+
<Compile Include="System\Windows\Controls\PassiveScrollViewer.cs" />
420422
<Compile Include="System\Windows\Extensions\ColorExtensions.cs" />
421423
<Compile Include="System\Windows\Hardware\DisplayDpi.cs" />
422424
<Compile Include="System\Windows\WindowBackdropType.cs" />
@@ -1153,6 +1155,9 @@
11531155
<Compile Include="System\Windows\Input\Command\CommandConverter.cs" />
11541156
<Compile Include="System\Windows\Input\Command\CommandValueSerializer.cs" />
11551157
<Compile Include="System\Windows\Input\KeyboardNavigation.cs" />
1158+
<Compile Include="System\Windows\Input\IRelayCommand.cs" />
1159+
<Compile Include="System\Windows\Input\RelayCommand{T}.cs" />
1160+
<Compile Include="System\Windows\Input\IRelayCommand{T}.cs" />
11561161
<Compile Include="System\Windows\Interop\ActiveXHost.cs" />
11571162
<Compile Include="System\Windows\Interop\BrowserInteropHelper.cs" />
11581163
<Compile Include="System\Windows\Interop\DynamicScriptObject.cs" />
@@ -1204,6 +1209,7 @@
12041209
<Compile Include="System\Windows\Markup\BamlRecordWriter.cs" />
12051210
<Compile Include="System\Windows\Markup\BamlVersionHeader.cs" />
12061211
<Compile Include="System\Windows\Markup\BamlWriter.cs" />
1212+
<Compile Include="System\Windows\Markup\ControlsDictionary.cs" />
12071213
<Compile Include="System\Windows\Markup\DependencyPropertyConverter.cs" />
12081214
<Compile Include="System\Windows\Markup\FilteredXmlReader.cs" />
12091215
<Compile Include="System\Windows\Markup\IHaveResources.cs" />
@@ -1235,6 +1241,9 @@
12351241
<Compile Include="System\Windows\Markup\StyleModeStack.cs" />
12361242
<Compile Include="System\Windows\Markup\TemplateComponentConnector.cs" />
12371243
<Compile Include="System\Windows\Markup\TemplateKeyConverter.cs" />
1244+
<Compile Include="System\Windows\Markup\ThemeResource.cs" />
1245+
<Compile Include="System\Windows\Markup\ThemeResourceExtension.cs" />
1246+
<Compile Include="System\Windows\Markup\ThemesDictionary.cs" />
12381247
<Compile Include="System\Windows\Markup\TypeContext.cs" />
12391248
<Compile Include="System\Windows\Markup\WpfXamlLoader.cs" />
12401249
<Compile Include="System\Windows\Markup\XamlBrushSerializer.cs" />

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Appearance/ApplicationThemeManager.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static class ApplicationThemeManager
3838
{
3939
private static ApplicationTheme _cachedApplicationTheme = ApplicationTheme.Unknown;
4040

41-
internal const string LibraryNamespace = "win11;";
41+
internal const string LibraryNamespace = "PresentationFramework.win11;";
4242

4343
internal const string ThemesDictionaryPath = "pack://application:,,,/PresentationFramework.Win11;component/Resources/Theme/";
4444

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
4+
// All Rights Reserved.
5+
6+
namespace System.Windows.Controls;
7+
8+
/// <summary>
9+
/// Decides where to put the element.
10+
/// </summary>
11+
public enum ElementPlacement
12+
{
13+
/// <summary>
14+
/// Puts the control element on the left.
15+
/// </summary>
16+
Left,
17+
18+
/// <summary>
19+
/// Puts the control element on the right.
20+
/// </summary>
21+
Right
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// This Source Code Form is subject to the terms of the MIT License.
2+
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
3+
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
4+
// All Rights Reserved.
5+
6+
using System.Windows.Controls;
7+
using System.Windows.Input;
8+
9+
namespace System.Windows.Controls;
10+
11+
/// <summary>
12+
/// A custom ScrollViewer that allows certain mouse events to bubble through when it's inactive.
13+
/// </summary>
14+
public class PassiveScrollViewer : ScrollViewer
15+
{
16+
/// <summary>Identifies the <see cref="IsScrollSpillEnabled"/> dependency property.</summary>
17+
public static readonly DependencyProperty IsScrollSpillEnabledProperty = DependencyProperty.Register(
18+
nameof(IsScrollSpillEnabled),
19+
typeof(bool),
20+
typeof(PassiveScrollViewer),
21+
new PropertyMetadata(true)
22+
);
23+
24+
/// <summary>
25+
/// Gets or sets a value indicating whether blocked inner scrolling should be propagated forward.
26+
/// </summary>
27+
public bool IsScrollSpillEnabled
28+
{
29+
get { return (bool)GetValue(IsScrollSpillEnabledProperty); }
30+
set { SetValue(IsScrollSpillEnabledProperty, value); }
31+
}
32+
33+
protected override void OnMouseWheel(MouseWheelEventArgs e)
34+
{
35+
if (
36+
IsVerticalScrollingDisabled
37+
|| IsContentSmallerThanViewport
38+
|| (IsScrollSpillEnabled && HasReachedEndOfScrolling(e))
39+
)
40+
{
41+
return;
42+
}
43+
44+
base.OnMouseWheel(e);
45+
}
46+
47+
private bool IsVerticalScrollingDisabled => VerticalScrollBarVisibility == ScrollBarVisibility.Disabled;
48+
49+
private bool IsContentSmallerThanViewport => ScrollableHeight <= 0;
50+
51+
private bool HasReachedEndOfScrolling(MouseWheelEventArgs e)
52+
{
53+
var isScrollingUp = e.Delta > 0;
54+
var isScrollingDown = e.Delta < 0;
55+
var isTopOfViewport = VerticalOffset == 0;
56+
var isBottomOfViewport = VerticalOffset >= ScrollableHeight;
57+
58+
return (isScrollingUp && isTopOfViewport) || (isScrollingDown && isBottomOfViewport);
59+
}
60+
}

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RichTextBox.cs

+19
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,25 @@ public bool IsDocumentEnabled
521521
}
522522
}
523523

524+
/// <summary>
525+
/// Property for <see cref="IsTextSelectionEnabledProperty"/>.
526+
/// </summary>
527+
public static readonly DependencyProperty IsTextSelectionEnabledProperty = DependencyProperty.Register(
528+
nameof(IsTextSelectionEnabled),
529+
typeof(bool),
530+
typeof(RichTextBox),
531+
new PropertyMetadata(false)
532+
);
533+
534+
/// <summary>
535+
/// TODO
536+
/// </summary>
537+
public bool IsTextSelectionEnabled
538+
{
539+
get => (bool)GetValue(IsTextSelectionEnabledProperty);
540+
set => SetValue(IsTextSelectionEnabledProperty, value);
541+
}
542+
524543
// ...........................................................
525544
//
526545
// Content Accessing Properties

src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextBox.cs

+224
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ public TextBox() : base()
9797

9898
// TextBox only accepts plain text, so change TextEditor's default to that.
9999
this.TextEditor.AcceptsRichContent = false;
100+
101+
SetValue(TemplateButtonCommandProperty, new RelayCommand<string>(OnTemplateButtonClick));
102+
100103
}
101104

102105
#endregion Constructors
@@ -962,7 +965,228 @@ public Typography Typography
962965
return new Typography(this);
963966
}
964967
}
968+
969+
/// <summary>
970+
/// Property for <see cref="Icon"/>.
971+
/// </summary>
972+
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
973+
nameof(Icon),
974+
typeof(IconElement),
975+
typeof(TextBox),
976+
new PropertyMetadata(null, null, IconSourceElementConverter.ConvertToIconElement)
977+
);
978+
979+
/// <summary>
980+
/// Property for <see cref="IconPlacement"/>.
981+
/// </summary>
982+
public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register(
983+
nameof(IconPlacement),
984+
typeof(ElementPlacement),
985+
typeof(TextBox),
986+
new PropertyMetadata(ElementPlacement.Left)
987+
);
988+
989+
/// <summary>
990+
/// Property for <see cref="PlaceholderText"/>.
991+
/// </summary>
992+
public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register(
993+
nameof(PlaceholderText),
994+
typeof(string),
995+
typeof(TextBox),
996+
new PropertyMetadata(String.Empty)
997+
);
998+
999+
/// <summary>
1000+
/// Property for <see cref="PlaceholderEnabled"/>.
1001+
/// </summary>
1002+
public static readonly DependencyProperty PlaceholderEnabledProperty = DependencyProperty.Register(
1003+
nameof(PlaceholderEnabled),
1004+
typeof(bool),
1005+
typeof(TextBox),
1006+
new PropertyMetadata(true)
1007+
);
1008+
1009+
/// <summary>
1010+
/// Property for <see cref="ClearButtonEnabled"/>.
1011+
/// </summary>
1012+
public static readonly DependencyProperty ClearButtonEnabledProperty = DependencyProperty.Register(
1013+
nameof(ClearButtonEnabled),
1014+
typeof(bool),
1015+
typeof(TextBox),
1016+
new PropertyMetadata(true)
1017+
);
9651018

1019+
/// <summary>
1020+
/// Property for <see cref="ShowClearButton"/>.
1021+
/// </summary>
1022+
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(
1023+
nameof(ShowClearButton),
1024+
typeof(bool),
1025+
typeof(TextBox),
1026+
new PropertyMetadata(false)
1027+
);
1028+
1029+
/// <summary>
1030+
/// Property for <see cref="IsTextSelectionEnabledProperty"/>.
1031+
/// </summary>
1032+
public static readonly DependencyProperty IsTextSelectionEnabledProperty = DependencyProperty.Register(
1033+
nameof(IsTextSelectionEnabled),
1034+
typeof(bool),
1035+
typeof(TextBox),
1036+
new PropertyMetadata(false)
1037+
);
1038+
1039+
/// <summary>
1040+
/// Property for <see cref="TemplateButtonCommand"/>.
1041+
/// </summary>
1042+
public static readonly DependencyProperty TemplateButtonCommandProperty = DependencyProperty.Register(
1043+
nameof(TemplateButtonCommand),
1044+
typeof(IRelayCommand),
1045+
typeof(TextBox),
1046+
new PropertyMetadata(null)
1047+
);
1048+
1049+
#region Properties
1050+
1051+
/// <summary>
1052+
/// Gets or sets displayed <see cref="IconElement"/>.
1053+
/// </summary>
1054+
public IconElement Icon
1055+
{
1056+
get => (IconElement)GetValue(IconProperty);
1057+
set => SetValue(IconProperty, value);
1058+
}
1059+
1060+
/// <summary>
1061+
/// Defines which side the icon should be placed on.
1062+
/// </summary>
1063+
public ElementPlacement IconPlacement
1064+
{
1065+
get => (ElementPlacement)GetValue(IconPlacementProperty);
1066+
set => SetValue(IconPlacementProperty, value);
1067+
}
1068+
1069+
/// <summary>
1070+
/// Gets or sets numbers pattern.
1071+
/// </summary>
1072+
public string PlaceholderText
1073+
{
1074+
get => (string)GetValue(PlaceholderTextProperty);
1075+
set => SetValue(PlaceholderTextProperty, value);
1076+
}
1077+
1078+
/// <summary>
1079+
/// Gets or sets a value determining whether to display the placeholder.
1080+
/// </summary>
1081+
public bool PlaceholderEnabled
1082+
{
1083+
get => (bool)GetValue(PlaceholderEnabledProperty);
1084+
set => SetValue(PlaceholderEnabledProperty, value);
1085+
}
1086+
1087+
/// <summary>
1088+
/// Gets or sets a value determining whether to enable the clear button.
1089+
/// </summary>
1090+
public bool ClearButtonEnabled
1091+
{
1092+
get => (bool)GetValue(ClearButtonEnabledProperty);
1093+
set => SetValue(ClearButtonEnabledProperty, value);
1094+
}
1095+
1096+
/// <summary>
1097+
/// Gets or sets a value determining whether to show the clear button when <see cref="TextBox"/> is focused.
1098+
/// </summary>
1099+
public bool ShowClearButton
1100+
{
1101+
get => (bool)GetValue(ShowClearButtonProperty);
1102+
protected set => SetValue(ShowClearButtonProperty, value);
1103+
}
1104+
1105+
/// <summary>
1106+
/// TODO
1107+
/// </summary>
1108+
public bool IsTextSelectionEnabled
1109+
{
1110+
get => (bool)GetValue(IsTextSelectionEnabledProperty);
1111+
set => SetValue(IsTextSelectionEnabledProperty, value);
1112+
}
1113+
1114+
/// <summary>
1115+
/// Command triggered after clicking the button.
1116+
/// </summary>
1117+
public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty);
1118+
1119+
#endregion
1120+
1121+
1122+
1123+
/// <inheritdoc />
1124+
protected override void OnTextChanged(TextChangedEventArgs e)
1125+
{
1126+
base.OnTextChanged(e);
1127+
1128+
if (PlaceholderEnabled && Text.Length > 0)
1129+
PlaceholderEnabled = false;
1130+
1131+
if (!PlaceholderEnabled && Text.Length < 1)
1132+
PlaceholderEnabled = true;
1133+
1134+
RevealClearButton();
1135+
}
1136+
1137+
/// <inheritdoc />
1138+
protected override void OnGotFocus(RoutedEventArgs e)
1139+
{
1140+
base.OnGotFocus(e);
1141+
1142+
CaretIndex = Text.Length;
1143+
1144+
RevealClearButton();
1145+
}
1146+
1147+
/// <inheritdoc />
1148+
protected override void OnLostFocus(RoutedEventArgs e)
1149+
{
1150+
base.OnLostFocus(e);
1151+
1152+
HideClearButton();
1153+
}
1154+
1155+
/// <summary>
1156+
/// Reveals the clear button by <see cref="ShowClearButton"/> property.
1157+
/// </summary>
1158+
protected void RevealClearButton()
1159+
{
1160+
if (ClearButtonEnabled && IsKeyboardFocusWithin)
1161+
ShowClearButton = Text.Length > 0;
1162+
}
1163+
1164+
/// <summary>
1165+
/// Hides the clear button by <see cref="ShowClearButton"/> property.
1166+
/// </summary>
1167+
protected void HideClearButton()
1168+
{
1169+
if (ClearButtonEnabled && !IsKeyboardFocusWithin && ShowClearButton)
1170+
ShowClearButton = false;
1171+
}
1172+
1173+
/// <summary>
1174+
/// Triggered when the user clicks the clear text button.
1175+
/// </summary>
1176+
protected virtual void OnClearButtonClick()
1177+
{
1178+
if (Text.Length > 0)
1179+
Text = string.Empty;
1180+
}
1181+
1182+
/// <summary>
1183+
/// Triggered by clicking a button in the control template.
1184+
/// </summary>
1185+
protected virtual void OnTemplateButtonClick(string parameter)
1186+
{
1187+
1188+
OnClearButtonClick();
1189+
}
9661190
#endregion Public Properties
9671191

9681192
//------------------------------------------------------

0 commit comments

Comments
 (0)