diff --git a/samples/BindingDemo/MainWindow.xaml b/samples/BindingDemo/MainWindow.xaml
index 9d68c8da8a..3ff80069f4 100644
--- a/samples/BindingDemo/MainWindow.xaml
+++ b/samples/BindingDemo/MainWindow.xaml
@@ -1,7 +1,7 @@
-
+
-
-
-
-
+
+
+
+
-
+
-
+
!BooleanString
!!BooleanString
@@ -43,24 +43,24 @@
-
+
-
-
-
-
+
-
+
@@ -91,19 +91,19 @@
-
+
-
+
-
-
+
+
-
+
-
-
+
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
index b682ebf51d..35e917f996 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
@@ -39,8 +39,12 @@
-
-
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
index 7a22c0ddab..8734758d26 100644
--- a/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
+++ b/samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
@@ -5,7 +5,7 @@
x:Class="ControlCatalog.Pages.CalendarDatePickerPage">
A control for selecting dates with a calendar drop-down
-
+
+ PlaceholderText="Placeholder"/>
-
+ PlaceholderText="Floating Placeholder"
+ UseFloatingPlaceholder="True"/>
+
+
+
+
-
+
-
+
diff --git a/samples/ControlCatalog/Pages/ClipboardPage.xaml b/samples/ControlCatalog/Pages/ClipboardPage.xaml
index 80b3f4d1ed..864a520aca 100644
--- a/samples/ControlCatalog/Pages/ClipboardPage.xaml
+++ b/samples/ControlCatalog/Pages/ClipboardPage.xaml
@@ -1,4 +1,4 @@
-
@@ -21,7 +21,7 @@
+ PlaceholderText="Text to copy of file names per line" />
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml
index 7320c1f3d7..f32cc601ab 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml
@@ -58,17 +58,17 @@
-
+
-
+
-
+
Desktop
@@ -80,17 +80,17 @@
-
+
-
+
+ PlaceholderText="Picked file content" />
diff --git a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
index b01b4a93bc..a112f79c02 100644
--- a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
+++ b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
@@ -1,4 +1,4 @@
-
- Watermark:
-
+ PlaceholderText:
+
Text:
@@ -81,23 +81,23 @@
+ PlaceholderText="Enter text" FormatString="{Binding SelectedFormat.Value}"/>
+ PlaceholderText="Enter text" FormatString="{Binding SelectedFormat.Value}"/>
-
+
+ PlaceholderText="Enter text" FormatString="{Binding SelectedFormat.Value}">
-
+
@@ -110,10 +110,18 @@
-
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index e2230e3cb6..346e561dfc 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -17,34 +17,41 @@
-
-
+
+
+
+
-
+
-
+
-
+
+ SelectionStart="5" SelectionEnd="22"
+ SelectionBrush="Green" SelectionForegroundBrush="Yellow" ClearSelectionOnLostFocus="False"/>
@@ -54,11 +61,11 @@
-
+
+ FontFamily="Comic Sans MS"
+ FontSize="10"
+ Foreground="Red"/>
-
diff --git a/samples/ControlCatalog/Pages/ThemePage.axaml b/samples/ControlCatalog/Pages/ThemePage.axaml
index 2d948c44a0..7eb95471a0 100644
--- a/samples/ControlCatalog/Pages/ThemePage.axaml
+++ b/samples/ControlCatalog/Pages/ThemePage.axaml
@@ -1,4 +1,4 @@
-
-
-
+
+
diff --git a/samples/Generators.Sandbox/Controls/SignUpView.xaml b/samples/Generators.Sandbox/Controls/SignUpView.xaml
index b256d7a31c..09313705f4 100644
--- a/samples/Generators.Sandbox/Controls/SignUpView.xaml
+++ b/samples/Generators.Sandbox/Controls/SignUpView.xaml
@@ -1,4 +1,4 @@
-
+ PlaceholderText="Please, enter user name..."
+ UseFloatingPlaceholder="True" />
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/samples/IntegrationTestApp/Pages/WindowDecorationsPage.axaml b/samples/IntegrationTestApp/Pages/WindowDecorationsPage.axaml
index d6b418952a..0a7dce9c02 100644
--- a/samples/IntegrationTestApp/Pages/WindowDecorationsPage.axaml
+++ b/samples/IntegrationTestApp/Pages/WindowDecorationsPage.axaml
@@ -10,7 +10,7 @@
-
+
diff --git a/samples/IntegrationTestApp/Pages/WindowPage.axaml b/samples/IntegrationTestApp/Pages/WindowPage.axaml
index 60900a4778..797c1c7170 100644
--- a/samples/IntegrationTestApp/Pages/WindowPage.axaml
+++ b/samples/IntegrationTestApp/Pages/WindowPage.axaml
@@ -6,7 +6,7 @@
x:Class="IntegrationTestApp.Pages.WindowPage">
-
+
NonOwned
Owned
diff --git a/samples/SafeAreaDemo/Views/MainView.xaml b/samples/SafeAreaDemo/Views/MainView.xaml
index 85163e7dad..c03ffc1f39 100644
--- a/samples/SafeAreaDemo/Views/MainView.xaml
+++ b/samples/SafeAreaDemo/Views/MainView.xaml
@@ -24,7 +24,7 @@
+ HorizontalContentAlignment="Right">View Bounds
Use Safe Area
Automatic Paddings
Hide System Bars
-
+
diff --git a/samples/SingleProjectSandbox/MainView.axaml b/samples/SingleProjectSandbox/MainView.axaml
index e1764b0795..b7f1bdaa53 100644
--- a/samples/SingleProjectSandbox/MainView.axaml
+++ b/samples/SingleProjectSandbox/MainView.axaml
@@ -5,10 +5,10 @@
x:DataType="local:MainView">
-
-
-
-
+
+
+
+
diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs
index 45566f186b..1faa9b340e 100644
--- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs
@@ -1,4 +1,4 @@
-// (c) Copyright Microsoft Corporation.
+// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
@@ -24,8 +24,37 @@ namespace Avalonia.Controls
defaultValue: 0,
defaultBindingMode: BindingMode.TwoWay));
- public static readonly StyledProperty WatermarkProperty =
- TextBox.WatermarkProperty.AddOwner();
+ ///
+ /// Defines the property.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013",
+ Justification = "We keep WatermarkProperty for backward compatibility.")]
+ public static readonly StyledProperty PlaceholderTextProperty =
+ TextBox.PlaceholderTextProperty.AddOwner();
+
+ ///
+ /// Defines the property.
+ ///
+ [Obsolete("Use PlaceholderTextProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkProperty = PlaceholderTextProperty;
+
+ ///
+ /// Defines the property.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013",
+ Justification = "We keep WatermarkForegroundProperty for backward compatibility.")]
+ public static readonly StyledProperty PlaceholderForegroundProperty =
+ TextBox.PlaceholderForegroundProperty.AddOwner();
+
+ ///
+ /// Defines the property.
+ ///
+ [Obsolete("Use PlaceholderForegroundProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkForegroundProperty = PlaceholderForegroundProperty;
///
/// Identifies the property.
@@ -406,10 +435,46 @@ namespace Avalonia.Controls
set => SetValue(FilterModeProperty, value);
}
+ ///
+ /// Gets or sets the placeholder or descriptive text that is displayed even if the text is not yet set.
+ ///
+ public string? PlaceholderText
+ {
+ get => GetValue(PlaceholderTextProperty);
+ set => SetValue(PlaceholderTextProperty, value);
+ }
+
+ ///
+ /// Gets or sets the placeholder or descriptive text that is displayed even if the text is not yet set.
+ ///
+ [Obsolete("Use PlaceholderText instead.", false)]
public string? Watermark
{
- get => GetValue(WatermarkProperty);
- set => SetValue(WatermarkProperty, value);
+ get => PlaceholderText;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderText = value;
+ }
+
+ ///
+ /// Gets or sets the brush used for the foreground color of the placeholder text.
+ ///
+ public Media.IBrush? PlaceholderForeground
+ {
+ get => GetValue(PlaceholderForegroundProperty);
+ set => SetValue(PlaceholderForegroundProperty, value);
+ }
+
+ ///
+ /// Gets or sets the brush used for the foreground color of the placeholder text.
+ ///
+ [Obsolete("Use PlaceholderForeground instead.", false)]
+ public Media.IBrush? WatermarkForeground
+ {
+ get => PlaceholderForeground;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderForeground = value;
}
///
diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.Properties.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.Properties.cs
index 1454b4ab6c..864ba86ef0 100644
--- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.Properties.cs
+++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.Properties.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Layout;
@@ -53,7 +53,7 @@ namespace Avalonia.Controls
public static readonly StyledProperty SelectedDateProperty =
AvaloniaProperty.Register(
nameof(SelectedDate),
- enableDataValidation: true,
+ enableDataValidation: true,
defaultBindingMode:BindingMode.TwoWay);
///
@@ -80,17 +80,53 @@ namespace Avalonia.Controls
public static readonly StyledProperty TextProperty =
AvaloniaProperty.Register(nameof(Text));
+ ///
+ /// Defines the property.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013",
+ Justification = "We keep WatermarkProperty for backward compatibility.")]
+ public static readonly StyledProperty PlaceholderTextProperty =
+ TextBox.PlaceholderTextProperty.AddOwner();
+
///
/// Defines the property.
///
- public static readonly StyledProperty WatermarkProperty =
- TextBox.WatermarkProperty.AddOwner();
+ [Obsolete("Use PlaceholderTextProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkProperty = PlaceholderTextProperty;
+
+ ///
+ /// Defines the property.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013",
+ Justification = "We keep UseFloatingWatermarkProperty for backward compatibility.")]
+ public static readonly StyledProperty UseFloatingPlaceholderProperty =
+ TextBox.UseFloatingPlaceholderProperty.AddOwner();
///
/// Defines the property.
///
- public static readonly StyledProperty UseFloatingWatermarkProperty =
- TextBox.UseFloatingWatermarkProperty.AddOwner();
+ [Obsolete("Use UseFloatingPlaceholderProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty UseFloatingWatermarkProperty = UseFloatingPlaceholderProperty;
+
+ ///
+ /// Defines the property.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013",
+ Justification = "We keep WatermarkForegroundProperty for backward compatibility.")]
+ public static readonly StyledProperty PlaceholderForegroundProperty =
+ TextBox.PlaceholderForegroundProperty.AddOwner();
+
+ ///
+ /// Defines the property.
+ ///
+ [Obsolete("Use PlaceholderForegroundProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkForegroundProperty = PlaceholderForegroundProperty;
///
/// Defines the property.
@@ -130,7 +166,7 @@ namespace Avalonia.Controls
get => GetValue(DisplayDateProperty);
set => SetValue(DisplayDateProperty, value);
}
-
+
///
/// Gets or sets the first date to be displayed.
///
@@ -254,18 +290,55 @@ namespace Avalonia.Controls
set => SetValue(TextProperty, value);
}
+ ///
+ public string? PlaceholderText
+ {
+ get => GetValue(PlaceholderTextProperty);
+ set => SetValue(PlaceholderTextProperty, value);
+ }
+
///
+ [Obsolete("Use PlaceholderText instead.", false)]
public string? Watermark
{
- get => GetValue(WatermarkProperty);
- set => SetValue(WatermarkProperty, value);
+ get => PlaceholderText;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderText = value;
+ }
+
+ ///
+ public bool UseFloatingPlaceholder
+ {
+ get => GetValue(UseFloatingPlaceholderProperty);
+ set => SetValue(UseFloatingPlaceholderProperty, value);
}
///
+ [Obsolete("Use UseFloatingPlaceholder instead.", false)]
public bool UseFloatingWatermark
{
- get => GetValue(UseFloatingWatermarkProperty);
- set => SetValue(UseFloatingWatermarkProperty, value);
+ get => UseFloatingPlaceholder;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => UseFloatingPlaceholder = value;
+ }
+
+ ///
+ public Media.IBrush? PlaceholderForeground
+ {
+ get => GetValue(PlaceholderForegroundProperty);
+ set => SetValue(PlaceholderForegroundProperty, value);
+ }
+
+ ///
+ [Obsolete("Use PlaceholderForeground instead.", false)]
+ public Media.IBrush? WatermarkForeground
+ {
+ get => PlaceholderForeground;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderForeground = value;
}
///
diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
index e3ce49ac96..c07d43b77c 100644
--- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
+++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
@@ -570,7 +570,7 @@ namespace Avalonia.Controls
private void Calendar_PointerReleased(object? sender, PointerReleasedEventArgs e)
{
-
+
if (e.InitialPressMouseButton == MouseButton.Left)
{
e.Handled = true;
@@ -779,7 +779,7 @@ namespace Avalonia.Controls
return true;
}
case Key.Down:
- {
+ {
if ((e.KeyModifiers & KeyModifiers.Control) == KeyModifiers.Control)
{
TogglePopUp();
@@ -816,7 +816,7 @@ namespace Avalonia.Controls
}
}
DateTime? d = SetTextBoxValue(s);
-
+
if (SelectedDate != d)
{
SetCurrentValue(SelectedDateProperty, d);
@@ -880,39 +880,39 @@ namespace Avalonia.Controls
if (_textBox != null)
{
SetCurrentValue(TextProperty, String.Empty);
-
- if (string.IsNullOrEmpty(Watermark) && !UseFloatingWatermark)
+
+ if (string.IsNullOrEmpty(PlaceholderText) && !UseFloatingPlaceholder)
{
DateTimeFormatInfo dtfi = DateTimeHelper.GetCurrentDateFormat();
_defaultText = string.Empty;
- var watermarkFormat = "<{0}>";
- string watermarkText;
+ var placeholderFormat = "<{0}>";
+ string placeholderText;
switch (SelectedDateFormat)
{
case CalendarDatePickerFormat.Custom:
{
- watermarkText = string.Format(CultureInfo.CurrentCulture, watermarkFormat, CustomDateFormatString);
+ placeholderText = string.Format(CultureInfo.CurrentCulture, placeholderFormat, CustomDateFormatString);
break;
}
case CalendarDatePickerFormat.Long:
{
- watermarkText = string.Format(CultureInfo.CurrentCulture, watermarkFormat, dtfi.LongDatePattern.ToString());
+ placeholderText = string.Format(CultureInfo.CurrentCulture, placeholderFormat, dtfi.LongDatePattern.ToString());
break;
}
case CalendarDatePickerFormat.Short:
default:
{
- watermarkText = string.Format(CultureInfo.CurrentCulture, watermarkFormat, dtfi.ShortDatePattern.ToString());
+ placeholderText = string.Format(CultureInfo.CurrentCulture, placeholderFormat, dtfi.ShortDatePattern.ToString());
break;
}
}
- _textBox.Watermark = watermarkText;
+ _textBox.PlaceholderText = placeholderText;
}
else
{
- _textBox.ClearValue(TextBox.WatermarkProperty);
+ _textBox.ClearValue(TextBox.PlaceholderTextProperty);
}
}
}
diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
index 188497d230..ab3861db47 100644
--- a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
+++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -108,11 +108,35 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(Value), coerce: (s,v) => ((NumericUpDown)s).OnCoerceValue(v),
defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty PlaceholderTextProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderText));
+
///
/// Defines the property.
///
- public static readonly StyledProperty WatermarkProperty =
- AvaloniaProperty.Register(nameof(Watermark));
+ [Obsolete("Use PlaceholderTextProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkProperty = PlaceholderTextProperty;
+
+ ///
+ /// Defines the property.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1013",
+ Justification = "We keep WatermarkForegroundProperty for backward compatibility.")]
+ public static readonly StyledProperty PlaceholderForegroundProperty =
+ TextBox.PlaceholderForegroundProperty.AddOwner();
+
+ ///
+ /// Defines the property.
+ ///
+ [Obsolete("Use PlaceholderForegroundProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkForegroundProperty = PlaceholderForegroundProperty;
///
/// Defines the property.
@@ -253,7 +277,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the parsing style (AllowLeadingWhite, Float, AllowHexSpecifier, ...). By default, Any.
- /// Note that Hex style does not work with decimal.
+ /// Note that Hex style does not work with decimal.
/// For hexadecimal display, use .
///
public NumberStyles ParsingNumberStyle
@@ -273,7 +297,7 @@ namespace Avalonia.Controls
///
/// Gets or sets the custom bidirectional Text-Value converter.
- /// Non-null converter overrides , providing finer control over
+ /// Non-null converter overrides , providing finer control over
/// string representation of the underlying value.
///
public IValueConverter? TextConverter
@@ -292,12 +316,45 @@ namespace Avalonia.Controls
}
///
- /// Gets or sets the object to use as a watermark if the is null.
+ /// Gets or sets the object to use as a placeholder if the is null.
+ ///
+ public string? PlaceholderText
+ {
+ get => GetValue(PlaceholderTextProperty);
+ set => SetValue(PlaceholderTextProperty, value);
+ }
+
+ ///
+ /// Gets or sets the object to use as a placeholder if the is null.
///
+ [Obsolete("Use PlaceholderText instead.", false)]
public string? Watermark
{
- get => GetValue(WatermarkProperty);
- set => SetValue(WatermarkProperty, value);
+ get => PlaceholderText;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderText = value;
+ }
+
+ ///
+ /// Gets or sets the brush used for the foreground color of the placeholder text.
+ ///
+ public Media.IBrush? PlaceholderForeground
+ {
+ get => GetValue(PlaceholderForegroundProperty);
+ set => SetValue(PlaceholderForegroundProperty, value);
+ }
+
+ ///
+ /// Gets or sets the brush used for the foreground color of the placeholder text.
+ ///
+ [Obsolete("Use PlaceholderForeground instead.", false)]
+ public Media.IBrush? WatermarkForeground
+ {
+ get => PlaceholderForeground;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderForeground = value;
}
///
@@ -700,8 +757,8 @@ namespace Avalonia.Controls
}
else
{
- // if Minimum is set we set value to Minimum on Increment.
- // otherwise we set value to 0. It ill be clamped to be between Minimum and Maximum later, so we don't need to do it here.
+ // if Minimum is set we set value to Minimum on Increment.
+ // otherwise we set value to 0. It ill be clamped to be between Minimum and Maximum later, so we don't need to do it here.
result = IsSet(MinimumProperty) ? Minimum : 0;
}
@@ -721,8 +778,8 @@ namespace Avalonia.Controls
}
else
{
- // if Maximum is set we set value to Maximum on decrement.
- // otherwise we set value to 0. It ill be clamped to be between Minimum and Maximum later, so we don't need to do it here.
+ // if Maximum is set we set value to Maximum on decrement.
+ // otherwise we set value to 0. It ill be clamped to be between Minimum and Maximum later, so we don't need to do it here.
result = IsSet(MaximumProperty) ? Maximum : 0;
}
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index b501722676..447a6a41fc 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -48,13 +48,13 @@ namespace Avalonia.Controls
///
/// Defines the property
///
- public static readonly StyledProperty IsInactiveSelectionHighlightEnabledProperty =
+ public static readonly StyledProperty IsInactiveSelectionHighlightEnabledProperty =
AvaloniaProperty.Register(nameof(IsInactiveSelectionHighlightEnabled), defaultValue: true);
///
/// Defines the property
///
- public static readonly StyledProperty ClearSelectionOnLostFocusProperty =
+ public static readonly StyledProperty ClearSelectionOnLostFocusProperty =
AvaloniaProperty.Register(nameof(ClearSelectionOnLostFocus), defaultValue: true);
///
@@ -181,16 +181,46 @@ namespace Avalonia.Controls
TextBlock.LineHeightProperty.AddOwner(new(defaultValue: double.NaN));
///
- /// Defines the property
+ /// Defines the property.
///
- public static readonly StyledProperty WatermarkProperty =
- AvaloniaProperty.Register(nameof(Watermark));
+ public static readonly StyledProperty PlaceholderTextProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderText));
///
- /// Defines the property
+ /// Defines the property.
///
- public static readonly StyledProperty UseFloatingWatermarkProperty =
- AvaloniaProperty.Register(nameof(UseFloatingWatermark));
+ [Obsolete("Use PlaceholderTextProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkProperty = PlaceholderTextProperty;
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty UseFloatingPlaceholderProperty =
+ AvaloniaProperty.Register(nameof(UseFloatingPlaceholder));
+
+ ///
+ /// Defines the property.
+ ///
+ [Obsolete("Use UseFloatingPlaceholderProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty UseFloatingWatermarkProperty = UseFloatingPlaceholderProperty;
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty PlaceholderForegroundProperty =
+ AvaloniaProperty.Register(nameof(PlaceholderForeground));
+
+ ///
+ /// Defines the property.
+ ///
+ [Obsolete("Use PlaceholderForegroundProperty instead.", false)]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1022",
+ Justification = "Obsolete property alias for backward compatibility.")]
+ public static readonly StyledProperty WatermarkForegroundProperty = PlaceholderForegroundProperty;
///
/// Defines the property
@@ -394,8 +424,8 @@ namespace Avalonia.Controls
///
public bool ClearSelectionOnLostFocus
{
- get=> GetValue(ClearSelectionOnLostFocusProperty);
- set=> SetValue(ClearSelectionOnLostFocusProperty, value);
+ get => GetValue(ClearSelectionOnLostFocusProperty);
+ set => SetValue(ClearSelectionOnLostFocusProperty, value);
}
///
@@ -408,7 +438,7 @@ namespace Avalonia.Controls
}
///
- /// Gets or sets a value that determins whether the TextBox allows and displays tabs
+ /// Gets or sets a value that determines whether the TextBox allows and displays tabs
///
public bool AcceptsTab
{
@@ -516,7 +546,7 @@ namespace Avalonia.Controls
/// Gets or sets the end position of the text selected in the TextBox
///
///
- /// When the SelectionEnd is equal to , there is no
+ /// When the SelectionEnd is equal to , there is no
/// selected text and it marks the caret position
///
public int SelectionEnd
@@ -665,20 +695,67 @@ namespace Avalonia.Controls
/// Gets or sets the placeholder or descriptive text that is displayed even if the
/// property is not yet set.
///
+ public string? PlaceholderText
+ {
+ get => GetValue(PlaceholderTextProperty);
+ set => SetValue(PlaceholderTextProperty, value);
+ }
+
+ ///
+ /// Gets or sets the placeholder or descriptive text that is displayed even if the
+ /// property is not yet set.
+ ///
+ [Obsolete("Use PlaceholderText instead.", false)]
public string? Watermark
{
- get => GetValue(WatermarkProperty);
- set => SetValue(WatermarkProperty, value);
+ get => PlaceholderText;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderText = value;
}
///
- /// Gets or sets a value indicating whether the will still be shown above the
+ /// Gets or sets a value indicating whether the will still be shown above the
/// even after a text value is set.
///
+ public bool UseFloatingPlaceholder
+ {
+ get => GetValue(UseFloatingPlaceholderProperty);
+ set => SetValue(UseFloatingPlaceholderProperty, value);
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the will still be shown above the
+ /// even after a text value is set.
+ ///
+ [Obsolete("Use UseFloatingPlaceholder instead.", false)]
public bool UseFloatingWatermark
{
- get => GetValue(UseFloatingWatermarkProperty);
- set => SetValue(UseFloatingWatermarkProperty, value);
+ get => UseFloatingPlaceholder;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => UseFloatingPlaceholder = value;
+ }
+
+ ///
+ /// Gets or sets the brush used for the foreground color of the placeholder text.
+ ///
+ public IBrush? PlaceholderForeground
+ {
+ get => GetValue(PlaceholderForegroundProperty);
+ set => SetValue(PlaceholderForegroundProperty, value);
+ }
+
+ ///
+ /// Gets or sets the brush used for the foreground color of the placeholder text.
+ ///
+ [Obsolete("Use PlaceholderForeground instead.", false)]
+ public IBrush? WatermarkForeground
+ {
+ get => PlaceholderForeground;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("AvaloniaProperty", "AVP1012",
+ Justification = "Obsolete property setter for backward compatibility.")]
+ set => PlaceholderForeground = value;
}
///
@@ -1018,7 +1095,7 @@ namespace Avalonia.Controls
if(_presenter != null)
{
_presenter.ShowSelectionHighlight = true;
- }
+ }
// when navigating to a textbox via the tab key, select all text if
// 1) this textbox is *not* a multiline textbox
diff --git a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
index 462dfe0323..92c46ecd41 100644
--- a/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/AutoCompleteBox.xaml
@@ -1,4 +1,4 @@
-
@@ -20,7 +20,7 @@
-
+
@@ -34,7 +34,8 @@
-
@@ -74,5 +75,5 @@
-
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
index ce580764d7..3a8db8ae36 100644
--- a/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/CalendarDatePicker.xaml
@@ -1,4 +1,4 @@
-
@@ -92,8 +92,9 @@
CornerRadius="{TemplateBinding CornerRadius}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
- Watermark="{TemplateBinding Watermark}"
- UseFloatingWatermark="{TemplateBinding UseFloatingWatermark}"
+ PlaceholderText="{TemplateBinding PlaceholderText}"
+ PlaceholderForeground="{TemplateBinding PlaceholderForeground}"
+ UseFloatingPlaceholder="{TemplateBinding UseFloatingPlaceholder}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
@@ -112,7 +113,7 @@
-
diff --git a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
index bcba646461..d9ce927153 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ComboBox.xaml
@@ -1,4 +1,4 @@
-
@@ -16,7 +16,7 @@
Item 1
Item 2
-
+
@@ -126,7 +126,7 @@
Foreground="{TemplateBinding Foreground}"
Background="Transparent"
Text="{TemplateBinding Text, Mode=TwoWay}"
- Watermark="{TemplateBinding PlaceholderText}"
+ PlaceholderText="{TemplateBinding PlaceholderText}"
BorderThickness="0"
IsVisible="{TemplateBinding IsEditable}">
diff --git a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
index 598cec7ace..c980135eca 100644
--- a/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
@@ -1,4 +1,4 @@
-
@@ -184,7 +184,7 @@
IsVisible="{Binding ShowFilters}"
ItemsSource="{Binding Filters}"
SelectedItem="{Binding SelectedFilter}" />
-
+
@@ -344,7 +344,7 @@
-
+
diff --git a/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml b/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml
index 22b6ef045c..b6c19484e9 100644
--- a/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/NumericUpDown.xaml
@@ -1,21 +1,21 @@
-
+
-
+ Maximum="10"
+ Increment="0.5"
+ VerticalContentAlignment="Center"
+ HorizontalContentAlignment="Center"
+ ButtonSpinnerLocation="Left"
+ PlaceholderText="Enter text" />
Clear
Reveal Password
Password Revealed
-
-
- Content
+
+
+ Content
@@ -20,7 +20,7 @@
M 11.416016,10 20,1.4160156 18.583984,0 10,8.5839846 1.4160156,0 0,1.4160156 8.5839844,10 0,18.583985 1.4160156,20 10,11.416015 18.583984,20 20,18.583985 Z
m10.051 7.0032c2.215 0 4.0105 1.7901 4.0105 3.9984s-1.7956 3.9984-4.0105 3.9984c-2.215 0-4.0105-1.7901-4.0105-3.9984s1.7956-3.9984 4.0105-3.9984zm0 1.4994c-1.3844 0-2.5066 1.1188-2.5066 2.499s1.1222 2.499 2.5066 2.499 2.5066-1.1188 2.5066-2.499-1.1222-2.499-2.5066-2.499zm0-5.0026c4.6257 0 8.6188 3.1487 9.7267 7.5613 0.10085 0.40165-0.14399 0.80877-0.54686 0.90931-0.40288 0.10054-0.81122-0.14355-0.91208-0.54521-0.94136-3.7492-4.3361-6.4261-8.2678-6.4261-3.9334 0-7.3292 2.6792-8.2689 6.4306-0.10063 0.40171-0.50884 0.64603-0.91177 0.54571s-0.648-0.5073-0.54737-0.90901c1.106-4.4152 5.1003-7.5667 9.728-7.5667z
m0.21967 0.21965c-0.26627 0.26627-0.29047 0.68293-0.07262 0.97654l0.07262 0.08412 4.0346 4.0346c-1.922 1.3495-3.3585 3.365-3.9554 5.7495-0.10058 0.4018 0.14362 0.8091 0.54543 0.9097 0.40182 0.1005 0.80909-0.1436 0.90968-0.5455 0.52947-2.1151 1.8371-3.8891 3.5802-5.0341l1.8096 1.8098c-0.70751 0.7215-1.1438 1.71-1.1438 2.8003 0 2.2092 1.7909 4 4 4 1.0904 0 2.0788-0.4363 2.8004-1.1438l5.9193 5.9195c0.2929 0.2929 0.7677 0.2929 1.0606 0 0.2663-0.2662 0.2905-0.6829 0.0726-0.9765l-0.0726-0.0841-6.1135-6.1142 0.0012-0.0015-1.2001-1.1979-2.8699-2.8693 2e-3 -8e-4 -2.8812-2.8782 0.0012-0.0018-1.1333-1.1305-4.3064-4.3058c-0.29289-0.29289-0.76777-0.29289-1.0607 0zm7.9844 9.0458 3.5351 3.5351c-0.45 0.4358-1.0633 0.704-1.7392 0.704-1.3807 0-2.5-1.1193-2.5-2.5 0-0.6759 0.26824-1.2892 0.7041-1.7391zm1.7959-5.7655c-1.0003 0-1.9709 0.14807-2.8889 0.425l1.237 1.2362c0.5358-0.10587 1.0883-0.16119 1.6519-0.16119 3.9231 0 7.3099 2.6803 8.2471 6.4332 0.1004 0.4018 0.5075 0.6462 0.9094 0.5459 0.4019-0.1004 0.6463-0.5075 0.5459-0.9094-1.103-4.417-5.0869-7.5697-9.7024-7.5697zm0.1947 3.5093 3.8013 3.8007c-0.1018-2.0569-1.7488-3.7024-3.8013-3.8007z
-
+
@@ -99,6 +99,7 @@
+
@@ -132,11 +133,12 @@
Grid.Column="1"
Grid.ColumnSpan="1"
Margin="{TemplateBinding Padding}">
-
+
-
+
-
@@ -217,19 +218,12 @@
-
-
-
-
-
+
-
@@ -203,7 +205,7 @@
diff --git a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs
index b4e0a055e3..26ece37acf 100644
--- a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs
@@ -406,7 +406,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(control.Text, control.ItemSelector(input, selectedItem));
});
}
-
+
[Fact]
public void Text_Validation()
{
@@ -421,7 +421,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal([exception], DataValidationErrors.GetErrors(control));
});
}
-
+
[Fact]
public void Text_Validation_TextBox_Errors_Binding()
{
@@ -430,20 +430,20 @@ namespace Avalonia.Controls.UnitTests
// simulate the TemplateBinding that would be used within the AutoCompleteBox control theme for the inner PART_TextBox
// DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}"
textbox.Bind(DataValidationErrors.ErrorsProperty, control.GetBindingObservable(DataValidationErrors.ErrorsProperty));
-
+
var exception = new InvalidCastException("failed validation");
var textObservable = new BehaviorSubject(new BindingNotification(exception, BindingErrorType.DataValidationError));
control.Bind(AutoCompleteBox.TextProperty, textObservable);
Dispatcher.UIThread.RunJobs();
-
+
Assert.True(DataValidationErrors.GetHasErrors(control));
Assert.Equal([exception], DataValidationErrors.GetErrors(control));
-
+
Assert.True(DataValidationErrors.GetHasErrors(textbox));
Assert.Equal([exception], DataValidationErrors.GetErrors(textbox));
});
}
-
+
[Fact]
public void SelectedItem_Validation()
{
@@ -583,7 +583,7 @@ namespace Avalonia.Controls.UnitTests
}
///
- /// Retrieves a defined predicate filter through a new AutoCompleteBox
+ /// Retrieves a defined predicate filter through a new AutoCompleteBox
/// control instance.
///
/// The FilterMode of interest.
@@ -1283,5 +1283,18 @@ namespace Avalonia.Controls.UnitTests
IsOpen = true;
}
}
+
+ [Fact]
+ public void PlaceholderForeground_Can_Be_Set()
+ {
+ using (UnitTestApplication.Start(TestServices.StyledWindow))
+ {
+ var control = CreateControl();
+ control.PlaceholderText = "Search...";
+ control.PlaceholderForeground = Media.Brushes.Green;
+
+ Assert.Equal(Media.Brushes.Green, control.PlaceholderForeground);
+ }
+ }
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/CalendarDatePickerTests.cs b/tests/Avalonia.Controls.UnitTests/CalendarDatePickerTests.cs
index 9124c317b8..d97a9729fb 100644
--- a/tests/Avalonia.Controls.UnitTests/CalendarDatePickerTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/CalendarDatePickerTests.cs
@@ -117,7 +117,7 @@ namespace Avalonia.Controls.UnitTests
{
return new FuncControlTemplate((control, scope) =>
{
- var textBox =
+ var textBox =
new TextBox
{
Name = "PART_TextBox"
@@ -130,7 +130,7 @@ namespace Avalonia.Controls.UnitTests
var calendar =
new Calendar
{
- Name = "PART_Calendar",
+ Name = "PART_Calendar",
[!Calendar.SelectedDateProperty] = control[!CalendarDatePicker.SelectedDateProperty],
[!Calendar.DisplayDateProperty] = control[!CalendarDatePicker.DisplayDateProperty],
[!Calendar.DisplayDateStartProperty] = control[!CalendarDatePicker.DisplayDateStartProperty],
@@ -179,5 +179,18 @@ namespace Avalonia.Controls.UnitTests
});
}
+ [Fact]
+ public void PlaceholderForeground_Can_Be_Set()
+ {
+ using (UnitTestApplication.Start(Services))
+ {
+ var control = CreateControl();
+ control.PlaceholderText = "Select date";
+ control.PlaceholderForeground = Media.Brushes.Purple;
+
+ Assert.Equal(Media.Brushes.Purple, control.PlaceholderForeground);
+ }
+ }
+
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs b/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs
index ab8766e216..868b33d7bd 100644
--- a/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -58,7 +58,7 @@ namespace Avalonia.Controls.UnitTests
var spinner = GetSpinner(control);
spinner.RaiseEvent(new SpinEventArgs(Spinner.SpinEvent, direction));
-
+
Assert.Equal(control.Value, expected);
}
@@ -105,16 +105,16 @@ namespace Avalonia.Controls.UnitTests
// if min and max are not defined and value was null, 0 should be ne new value after spin
yield return [decimal.MinValue, decimal.MaxValue, null, SpinDirection.Decrease, 0m];
yield return [decimal.MinValue, decimal.MaxValue, null, SpinDirection.Increase, 0m];
-
+
// if no value was defined, but Min or Max are defined, use these as the new value
yield return [-400m, -200m, null, SpinDirection.Decrease, -200m];
yield return [200m, 400m, null, SpinDirection.Increase, 200m];
-
+
// Value should be clamped to Min / Max after spinning
yield return [200m, 400m, 5m, SpinDirection.Increase, 200m];
yield return [200m, 400m, 200m, SpinDirection.Decrease, 200m];
}
-
+
private void RunTest(Action test)
{
using (UnitTestApplication.Start(Services))
@@ -148,14 +148,14 @@ namespace Avalonia.Controls.UnitTests
.OfType()
.First();
}
-
+
private static ButtonSpinner GetSpinner(NumericUpDown control)
{
return control.GetTemplateChildren()
.OfType()
.First();
}
-
+
private static IControlTemplate CreateTemplate()
{
return new FuncControlTemplate((control, scope) =>
@@ -180,14 +180,27 @@ namespace Avalonia.Controls.UnitTests
{
// Set TabIndex on NumericUpDown
control.TabIndex = 5;
-
+
// The inner TextBox should inherit the same TabIndex
Assert.Equal(5, textbox.TabIndex);
-
+
// Change TabIndex and verify it gets synchronized
control.TabIndex = 10;
Assert.Equal(10, textbox.TabIndex);
});
}
+
+ [Fact]
+ public void PlaceholderForeground_Can_Be_Set()
+ {
+ using (UnitTestApplication.Start(Services))
+ {
+ var control = CreateControl();
+ control.PlaceholderText = "Enter value";
+ control.PlaceholderForeground = Media.Brushes.Red;
+
+ Assert.Equal(Media.Brushes.Red, control.PlaceholderForeground);
+ }
+ }
}
}
diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
index 3e830859a4..31b8fe45e8 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
@@ -42,25 +42,25 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
Text = "5678"
};
-
+
var sp = new StackPanel();
sp.Children.Add(target1);
sp.Children.Add(target2);
target1.ApplyTemplate();
target2.ApplyTemplate();
-
+
var root = new TestRoot() { Child = sp };
target1.SelectionStart = 0;
target1.SelectionEnd = 3;
-
+
target1.Focus();
Assert.False(target2.IsFocused);
Assert.True(target1.IsFocused);
target2.Focus();
-
+
Assert.Equal("123", target1.SelectedText);
}
}
@@ -106,7 +106,7 @@ namespace Avalonia.Controls.UnitTests
}
}
};
-
+
target1.ApplyTemplate();
@@ -165,16 +165,16 @@ namespace Avalonia.Controls.UnitTests
};
target.ApplyTemplate();
-
+
target.Measure(Size.Infinity);
-
+
target.CaretIndex = 3;
RaiseKeyEvent(target, Key.Right, 0);
Assert.Equal(4, target.CaretIndex);
}
}
-
+
[Fact]
public void Control_Backspace_Should_Set_Caret_Position_To_The_Start_Of_The_Deletion()
{
@@ -194,11 +194,11 @@ namespace Avalonia.Controls.UnitTests
// (First Second |Third)
RaiseKeyEvent(target, Key.Back, KeyModifiers.Control);
// (First |Third)
-
+
Assert.Equal(6, target.CaretIndex);
}
}
-
+
[Fact]
public void Control_Backspace_Should_Remove_The_Double_Whitespace_If_Caret_Index_Was_At_The_End_Of_A_Word()
{
@@ -213,7 +213,7 @@ namespace Avalonia.Controls.UnitTests
};
target.ApplyTemplate();
-
+
// (First Second| Third)
RaiseKeyEvent(target, Key.Back, KeyModifiers.Control);
// (First| Third)
@@ -236,11 +236,11 @@ namespace Avalonia.Controls.UnitTests
};
target.ApplyTemplate();
-
+
// (First Second| Third)
RaiseKeyEvent(target, Key.Back, KeyModifiers.Control);
// (First| Third)
-
+
target.Undo();
// (First Second| Third)
@@ -258,7 +258,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
Text = "1234"
};
-
+
target.ApplyTemplate();
RaiseKeyEvent(target, Key.A, KeyModifiers.Control);
@@ -314,7 +314,7 @@ namespace Avalonia.Controls.UnitTests
SelectionStart = 5,
SelectionEnd = 5
};
-
+
textBox.ApplyTemplate();
// (First| Second Third Fourth)
@@ -356,7 +356,7 @@ namespace Avalonia.Controls.UnitTests
Text = "First Second Third Fourth",
CaretIndex = 19,
};
-
+
textBox.ApplyTemplate();
// (First Second Third |Fourth)
@@ -400,7 +400,7 @@ namespace Avalonia.Controls.UnitTests
textBox.SelectionStart = 2;
textBox.SelectionEnd = 2;
-
+
Assert.Equal(2, textBox.CaretIndex);
}
}
@@ -443,7 +443,7 @@ namespace Avalonia.Controls.UnitTests
AcceptsReturn = false,
Text = "1234"
};
-
+
target.ApplyTemplate();
RaiseKeyEvent(target, Key.Enter, 0);
@@ -462,7 +462,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
AcceptsReturn = true
};
-
+
target.ApplyTemplate();
RaiseKeyEvent(target, Key.Enter, 0);
@@ -482,7 +482,7 @@ namespace Avalonia.Controls.UnitTests
AcceptsReturn = true,
NewLine = "Test"
};
-
+
target.ApplyTemplate();
RaiseKeyEvent(target, Key.Enter, 0);
@@ -523,7 +523,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
Text = "0123456789"
};
-
+
target.ApplyTemplate();
target.SelectionStart = 0;
@@ -547,7 +547,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
Text = "0123456789"
};
-
+
target.ApplyTemplate();
target.SelectionStart = 8;
@@ -592,7 +592,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
Text = "0123456789"
};
-
+
target.ApplyTemplate();
Assert.True(target.SelectedText == "");
@@ -614,7 +614,7 @@ namespace Avalonia.Controls.UnitTests
Template = CreateTemplate(),
Text = "0123"
};
-
+
target.ApplyTemplate();
target.SelectedText = "AA";
@@ -679,7 +679,7 @@ namespace Avalonia.Controls.UnitTests
Assert.True(true);
}
}
-
+
[Theory]
[InlineData(Key.Up)]
[InlineData(Key.Down)]
@@ -725,7 +725,7 @@ namespace Avalonia.Controls.UnitTests
target1.ApplyTemplate();
target2.ApplyTemplate();
-
+
var root = new TestRoot { Child = sp };
var gfcount = 0;
@@ -746,7 +746,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(1, lfcount);
}
}
-
+
[Fact]
public void TextBox_CaretIndex_Persists_When_Focus_Lost()
{
@@ -768,7 +768,7 @@ namespace Avalonia.Controls.UnitTests
target1.ApplyTemplate();
target2.ApplyTemplate();
-
+
var root = new TestRoot { Child = sp };
target2.Focus();
@@ -777,11 +777,11 @@ namespace Avalonia.Controls.UnitTests
Assert.True(target2.IsFocused);
target1.Focus();
-
+
Assert.Equal(2, target2.CaretIndex);
}
}
-
+
[Fact]
public void TextBox_Reveal_Password_Reset_When_Lost_Focus()
{
@@ -804,14 +804,14 @@ namespace Avalonia.Controls.UnitTests
target1.ApplyTemplate();
target2.ApplyTemplate();
-
+
var root = new TestRoot { Child = sp };
target1.Focus();
target1.RevealPassword = true;
-
+
target2.Focus();
-
+
Assert.False(target1.RevealPassword);
}
}
@@ -833,7 +833,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Null(target.Text);
}
}
-
+
[Theory]
[InlineData("abc", "d", 3, 0, 0, false, "abc")]
[InlineData("abc", "dd", 4, 3, 3, false, "abcd")]
@@ -870,7 +870,7 @@ namespace Avalonia.Controls.UnitTests
topLevel.LayoutManager.ExecuteInitialLayoutPass();
target.Measure(Size.Infinity);
-
+
if (fromClipboard)
{
await topLevel.Clipboard!.SetTextAsync(textInput);
@@ -882,7 +882,7 @@ namespace Avalonia.Controls.UnitTests
{
RaiseTextEvent(target, textInput);
}
-
+
Assert.Equal(expected, target.Text);
}
}
@@ -1246,7 +1246,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal((minLines * target.LineHeight) + textPresenterMargin.Top + textPresenterMargin.Bottom, scrollViewer.MinHeight);
}
}
-
+
[Theory]
[InlineData(null, 1)]
[InlineData("", 1)]
@@ -1285,7 +1285,7 @@ namespace Avalonia.Controls.UnitTests
var b = new TextBox();
Assert.Equal(-1, b.GetLineCount());
}
-
+
[Fact]
public void LineCount_Is_Correct_After_Text_Change()
{
@@ -1309,7 +1309,7 @@ namespace Avalonia.Controls.UnitTests
target.ApplyTemplate();
target.Measure(Size.Infinity);
-
+
Assert.Equal(1, target.GetLineCount());
target.Text = "Hello\r\nWorld";
@@ -1505,7 +1505,7 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal("ABCDEF123", tb.Text);
// Undo will take us back one step
- tb.Undo();
+ tb.Undo();
Assert.Equal("ABCDEF", tb.Text);
// Undo again
@@ -2050,7 +2050,7 @@ namespace Avalonia.Controls.UnitTests
Assert.NotNull(client);
Assert.Equal(string.Empty, client.SurroundingText);
}
-
+
[Fact]
public void Backspace_Should_Delete_Last_Character_In_Line_And_Keep_Caret_On_Same_Line()
{
@@ -2122,7 +2122,7 @@ namespace Avalonia.Controls.UnitTests
Assert.True(target1.IsFocused);
- Assert.Equal("1234", target1.SelectedText);
+ Assert.Equal("1234", target1.SelectedText);
target2.Focus();
@@ -2149,6 +2149,61 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal("FirstSecond", target.Text);
}
+ [Fact]
+ public void PlaceholderForeground_Can_Be_Set()
+ {
+ using (UnitTestApplication.Start(Services))
+ {
+ var target = new TextBox
+ {
+ Template = CreateTemplate(),
+ PlaceholderText = "Enter text",
+ PlaceholderForeground = Brushes.Red
+ };
+
+ target.ApplyTemplate();
+
+ Assert.Equal(Brushes.Red, target.PlaceholderForeground);
+ }
+ }
+
+ [Fact]
+ public void PlaceholderForeground_Defaults_To_Null()
+ {
+ using (UnitTestApplication.Start(Services))
+ {
+ var target = new TextBox
+ {
+ Template = CreateTemplate(),
+ PlaceholderText = "Enter text"
+ };
+
+ target.ApplyTemplate();
+
+ Assert.Null(target.PlaceholderForeground);
+ }
+ }
+
+ [Fact]
+ public void PlaceholderForeground_Can_Be_Set_To_Null()
+ {
+ using (UnitTestApplication.Start(Services))
+ {
+ var target = new TextBox
+ {
+ Template = CreateTemplate(),
+ PlaceholderText = "Enter text",
+ PlaceholderForeground = Brushes.Blue
+ };
+
+ target.ApplyTemplate();
+
+ target.PlaceholderForeground = null;
+
+ Assert.Null(target.PlaceholderForeground);
+ }
+ }
+
private static TestServices FocusServices => TestServices.MockThreadingInterface.With(
keyboardDevice: () => new KeyboardDevice(),
keyboardNavigation: () => new KeyboardNavigationHandler(),
@@ -2160,7 +2215,7 @@ namespace Avalonia.Controls.UnitTests
private static TestServices Services => TestServices.MockThreadingInterface.With(
standardCursorFactory: Mock.Of(),
renderInterface: new HeadlessPlatformRenderInterface(),
- textShaperImpl: new HarfBuzzTextShaper(),
+ textShaperImpl: new HarfBuzzTextShaper(),
fontManagerImpl: new TestFontManager(),
assetLoader: new StandardAssetLoader());
diff --git a/tests/Avalonia.Generators.Tests/Views/AttachedProps.xml b/tests/Avalonia.Generators.Tests/Views/AttachedProps.xml
index 209b7ca9f1..ccd199040e 100644
--- a/tests/Avalonia.Generators.Tests/Views/AttachedProps.xml
+++ b/tests/Avalonia.Generators.Tests/Views/AttachedProps.xml
@@ -3,6 +3,6 @@
x:Class="Sample.App.AttachedProps"
Design.Width="300">
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/ControlWithoutWindow.xml b/tests/Avalonia.Generators.Tests/Views/ControlWithoutWindow.xml
index 485fe93e4c..54e7f156e1 100644
--- a/tests/Avalonia.Generators.Tests/Views/ControlWithoutWindow.xml
+++ b/tests/Avalonia.Generators.Tests/Views/ControlWithoutWindow.xml
@@ -3,6 +3,6 @@
x:Class="Sample.App.ControlWithoutWindow"
Design.Width="300">
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/DataTemplates.xml b/tests/Avalonia.Generators.Tests/Views/DataTemplates.xml
index f7e15644aa..c4d587baf2 100644
--- a/tests/Avalonia.Generators.Tests/Views/DataTemplates.xml
+++ b/tests/Avalonia.Generators.Tests/Views/DataTemplates.xml
@@ -3,14 +3,14 @@
x:Class="Sample.App.DataTemplates">
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
+ Placeholder="Templated input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/FieldModifier.xml b/tests/Avalonia.Generators.Tests/Views/FieldModifier.xml
index 3ee5e51466..65fafb414e 100644
--- a/tests/Avalonia.Generators.Tests/Views/FieldModifier.xml
+++ b/tests/Avalonia.Generators.Tests/Views/FieldModifier.xml
@@ -4,20 +4,20 @@
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
+ Placeholder="Password input"
+ UseFloatingPlaceholder="True" />
+ Placeholder="Password input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/NamedControl.xml b/tests/Avalonia.Generators.Tests/Views/NamedControl.xml
index 0a3c3d3111..44aa833f3b 100644
--- a/tests/Avalonia.Generators.Tests/Views/NamedControl.xml
+++ b/tests/Avalonia.Generators.Tests/Views/NamedControl.xml
@@ -3,6 +3,6 @@
x:Class="Sample.App.NamedControl">
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/NamedControls.xml b/tests/Avalonia.Generators.Tests/Views/NamedControls.xml
index 6083ec794c..fb8d7c4c95 100644
--- a/tests/Avalonia.Generators.Tests/Views/NamedControls.xml
+++ b/tests/Avalonia.Generators.Tests/Views/NamedControls.xml
@@ -3,11 +3,11 @@
x:Class="Sample.App.NamedControls">
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
+ Placeholder="Password input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/NoNamedControls.xml b/tests/Avalonia.Generators.Tests/Views/NoNamedControls.xml
index 751d1574c8..3e9ba157fb 100644
--- a/tests/Avalonia.Generators.Tests/Views/NoNamedControls.xml
+++ b/tests/Avalonia.Generators.Tests/Views/NoNamedControls.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/tests/Avalonia.Generators.Tests/Views/SignUpView.xml b/tests/Avalonia.Generators.Tests/Views/SignUpView.xml
index a482e1fc5e..128fd0e260 100644
--- a/tests/Avalonia.Generators.Tests/Views/SignUpView.xml
+++ b/tests/Avalonia.Generators.Tests/Views/SignUpView.xml
@@ -5,15 +5,15 @@
+ Placeholder="Please, enter user name..."
+ UseFloatingPlaceholder="True" />
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Generators.Tests/Views/xNamedControls.xml b/tests/Avalonia.Generators.Tests/Views/xNamedControls.xml
index 00eec9b969..bd9bcccdec 100644
--- a/tests/Avalonia.Generators.Tests/Views/xNamedControls.xml
+++ b/tests/Avalonia.Generators.Tests/Views/xNamedControls.xml
@@ -3,11 +3,11 @@
x:Class="Sample.App.xNamedControls">
+ Placeholder="Username input"
+ UseFloatingPlaceholder="True" />
+ Placeholder="Password input"
+ UseFloatingPlaceholder="True" />
diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
index 0cb587f849..03871d2c84 100644
--- a/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
+++ b/tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests.cs
@@ -71,14 +71,14 @@ namespace Avalonia.Markup.Xaml.UnitTests.Data
-
+
-
+
diff --git a/tests/Avalonia.RenderTests/Controls/TextBoxTests.cs b/tests/Avalonia.RenderTests/Controls/TextBoxTests.cs
new file mode 100644
index 0000000000..8047f2d103
--- /dev/null
+++ b/tests/Avalonia.RenderTests/Controls/TextBoxTests.cs
@@ -0,0 +1,135 @@
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Presenters;
+using Avalonia.Controls.Templates;
+using Avalonia.Layout;
+using Avalonia.Media;
+using Xunit;
+
+namespace Avalonia.Skia.RenderTests
+{
+ public class TextBoxTests : TestBase
+ {
+ public TextBoxTests()
+ : base(@"Controls\TextBox")
+ {
+ }
+
+ private static IControlTemplate CreateTextBoxTemplate()
+ {
+ return new FuncControlTemplate((textBox, scope) =>
+ {
+ var border = new Border
+ {
+ Background = textBox.Background,
+ BorderBrush = Brushes.Gray,
+ BorderThickness = new Thickness(1),
+ Padding = new Thickness(4),
+ };
+
+ var panel = new Panel();
+
+ // Use Antialias mode
+ TextOptions.SetTextRenderingMode(panel, TextRenderingMode.Antialias);
+
+ var placeholder = new TextBlock
+ {
+ Name = "PART_Placeholder",
+ [!TextBlock.TextProperty] = textBox[!TextBox.PlaceholderTextProperty],
+ [!TextBlock.ForegroundProperty] = textBox[!TextBox.PlaceholderForegroundProperty],
+ FontFamily = textBox.FontFamily,
+ FontSize = textBox.FontSize,
+ VerticalAlignment = VerticalAlignment.Center,
+ Opacity = 0.5,
+ }.RegisterInNameScope(scope);
+
+ var presenter = new TextPresenter
+ {
+ Name = "PART_TextPresenter",
+ [!TextPresenter.TextProperty] = textBox[!TextBox.TextProperty],
+ [!TextPresenter.CaretIndexProperty] = textBox[!TextBox.CaretIndexProperty],
+ FontFamily = textBox.FontFamily,
+ FontSize = textBox.FontSize,
+ }.RegisterInNameScope(scope);
+
+ panel.Children.Add(placeholder);
+ panel.Children.Add(presenter);
+ border.Child = panel;
+
+ return border;
+ });
+ }
+
+ [Fact]
+ public async Task Placeholder_With_Red_Foreground()
+ {
+ var target = new Border
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 50,
+ Background = Brushes.White,
+ Child = new TextBox
+ {
+ Template = CreateTextBoxTemplate(),
+ FontFamily = TestFontFamily,
+ FontSize = 12,
+ Background = Brushes.White,
+ PlaceholderText = "Red placeholder",
+ PlaceholderForeground = Brushes.Red,
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task Placeholder_With_Blue_Foreground()
+ {
+ var target = new Border
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 50,
+ Background = Brushes.White,
+ Child = new TextBox
+ {
+ Template = CreateTextBoxTemplate(),
+ FontFamily = TestFontFamily,
+ FontSize = 12,
+ Background = Brushes.White,
+ PlaceholderText = "Blue placeholder",
+ PlaceholderForeground = Brushes.Blue,
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+
+ [Fact]
+ public async Task Placeholder_With_Default_Foreground()
+ {
+ var target = new Border
+ {
+ Padding = new Thickness(8),
+ Width = 200,
+ Height = 50,
+ Background = Brushes.White,
+ Child = new TextBox
+ {
+ Template = CreateTextBoxTemplate(),
+ FontFamily = TestFontFamily,
+ FontSize = 12,
+ Background = Brushes.White,
+ PlaceholderText = "Default placeholder",
+ PlaceholderForeground = Brushes.Gray,
+ }
+ };
+
+ await RenderToFile(target);
+ CompareImages();
+ }
+ }
+}
diff --git a/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Blue_Foreground.expected.png b/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Blue_Foreground.expected.png
new file mode 100644
index 0000000000..d2262f7e52
Binary files /dev/null and b/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Blue_Foreground.expected.png differ
diff --git a/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Default_Foreground.expected.png b/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Default_Foreground.expected.png
new file mode 100644
index 0000000000..770ff257b4
Binary files /dev/null and b/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Default_Foreground.expected.png differ
diff --git a/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Red_Foreground.expected.png b/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Red_Foreground.expected.png
new file mode 100644
index 0000000000..4d2bc5d78b
Binary files /dev/null and b/tests/TestFiles/Skia/Controls/TextBox/Placeholder_With_Red_Foreground.expected.png differ