From c65cef9e8a38c3d64bda4bfc0bb3c0fea005ff64 Mon Sep 17 00:00:00 2001 From: Anjali Date: Fri, 22 Dec 2023 14:31:37 +0530 Subject: [PATCH 1/2] Added TextBox styles Todo: Clear button not showing up --- .../PresentationFramework-ref.baseline.txt | 35 +- .../PresentationFramework.csproj | 4 + .../System/Windows/Controls/TextBox.cs | 231 +++++++++++ .../System/Windows/ElementPlacement.cs | 24 ++ .../System/Windows/Input/IRelayCommand.cs | 20 + .../System/Windows/Input/IRelayCommand{T}.cs | 32 ++ .../System/Windows/Input/RelayCommand{T}.cs | 191 +++++++++ .../Styles/TextBox.xaml | 362 ++++++++++++++++++ 8 files changed, 898 insertions(+), 1 deletion(-) create mode 100644 src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ElementPlacement.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand{T}.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/RelayCommand{T}.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Win11/Styles/TextBox.xaml diff --git a/src/Microsoft.DotNet.Wpf/ApiCompat/Baselines/PresentationFramework-ref.baseline.txt b/src/Microsoft.DotNet.Wpf/ApiCompat/Baselines/PresentationFramework-ref.baseline.txt index 4a62c93adfc..551fb3b386e 100644 --- a/src/Microsoft.DotNet.Wpf/ApiCompat/Baselines/PresentationFramework-ref.baseline.txt +++ b/src/Microsoft.DotNet.Wpf/ApiCompat/Baselines/PresentationFramework-ref.baseline.txt @@ -5,6 +5,7 @@ CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVi CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.DataTrigger.Binding' changed from '[LocalizabilityAttribute(0, Readability=0)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.None, Readability=Readability.Unreadable)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.DataTrigger.Setters' changed from '[DesignerSerializationVisibilityAttribute(2)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.DataTrigger.Value' changed from '[LocalizabilityAttribute(0, Readability=0)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.None, Readability=Readability.Unreadable)]' in the implementation. +TypesMustExist : Type 'System.Windows.ElementPlacement' does not exist in the implementation but it does exist in the contract. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.EventTrigger.Actions' changed from '[DesignerSerializationVisibilityAttribute(2)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.FrameworkContentElement.BindingGroup' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.FrameworkContentElement.BindingGroup' changed from '[LocalizabilityAttribute(17)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)]' in the implementation. @@ -210,6 +211,14 @@ CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'S CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.TextBlock.Inlines' changed from '[DesignerSerializationVisibilityAttribute(2)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Controls.TextBlock.Text' changed from '[LocalizabilityAttribute(1)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.Text)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Controls.TextBox' changed from '[LocalizabilityAttribute(1)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.Text)]' in the implementation. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.ClearButtonEnabledProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.IconPlacementProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.IconProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.IsTextSelectionEnabledProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.PlaceholderEnabledProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.PlaceholderTextProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.ShowClearButtonProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.DependencyProperty System.Windows.DependencyProperty System.Windows.Controls.TextBox.TemplateButtonCommandProperty' does not exist in the implementation but it does exist in the contract. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.TextBox.CaretIndex' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.TextBox.LineCount' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Controls.TextBox.MaxLength' changed from '[LocalizabilityAttribute(0, Modifiability=0)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.None, Modifiability=Modifiability.Unmodifiable)]' in the implementation. @@ -217,6 +226,27 @@ CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVi CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.TextBox.SelectionLength' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.TextBox.SelectionStart' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Controls.TextBox.Text' changed from '[LocalizabilityAttribute(1)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.Text)]' in the implementation. +MembersMustExist : Member 'public System.Boolean System.Windows.Controls.TextBox.ClearButtonEnabled.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.ClearButtonEnabled.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void System.Windows.Controls.TextBox.HideClearButton()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.Controls.IconElement System.Windows.Controls.TextBox.Icon.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.Icon.set(System.Windows.Controls.IconElement)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.ElementPlacement System.Windows.Controls.TextBox.IconPlacement.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.IconPlacement.set(System.Windows.ElementPlacement)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Boolean System.Windows.Controls.TextBox.IsTextSelectionEnabled.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.IsTextSelectionEnabled.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.Input.KeyboardNavigation System.Windows.Controls.TextBox.keyboardNavigation.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.keyboardNavigation.set(System.Windows.Input.KeyboardNavigation)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void System.Windows.Controls.TextBox.OnClearButtonClick()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void System.Windows.Controls.TextBox.OnTemplateButtonClick(System.String)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Boolean System.Windows.Controls.TextBox.PlaceholderEnabled.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.PlaceholderEnabled.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.String System.Windows.Controls.TextBox.PlaceholderText.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void System.Windows.Controls.TextBox.PlaceholderText.set(System.String)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void System.Windows.Controls.TextBox.RevealClearButton()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Boolean System.Windows.Controls.TextBox.ShowClearButton.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'protected void System.Windows.Controls.TextBox.ShowClearButton.set(System.Boolean)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public System.Windows.Input.IRelayCommand System.Windows.Controls.TextBox.TemplateButtonCommand.get()' does not exist in the implementation but it does exist in the contract. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.ToolBar.IsOverflowOpen' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Controls.ToolBarTray.ToolBars' changed from '[DesignerSerializationVisibilityAttribute(2)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Controls.ToolTip' changed from '[LocalizabilityAttribute(10)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.ToolTip)]' in the implementation. @@ -299,9 +329,12 @@ CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVi CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Documents.TextElement.FontFamily' changed from '[LocalizabilityAttribute(14, Modifiability=0)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.Font, Modifiability=Modifiability.Unmodifiable)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Documents.TextElement.FontSize' changed from '[LocalizabilityAttribute(0)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.None)]' in the implementation. CannotChangeAttribute : Attribute 'System.AttributeUsageAttribute' on 'System.Windows.Documents.TextElementEditingBehaviorAttribute' changed from '[AttributeUsageAttribute(4)]' in the contract to '[AttributeUsageAttribute(AttributeTargets.Class)]' in the implementation. +TypesMustExist : Type 'System.Windows.Input.IRelayCommand' does not exist in the implementation but it does exist in the contract. +TypesMustExist : Type 'System.Windows.Input.IRelayCommand' does not exist in the implementation but it does exist in the contract. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.DependencyProperty System.Windows.Input.KeyboardNavigation.ControlTabNavigationProperty' changed from '[LocalizabilityAttribute(17)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.DependencyProperty System.Windows.Input.KeyboardNavigation.DirectionalNavigationProperty' changed from '[LocalizabilityAttribute(17)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.DependencyProperty System.Windows.Input.KeyboardNavigation.TabNavigationProperty' changed from '[LocalizabilityAttribute(17)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)]' in the implementation. +TypesMustExist : Type 'System.Windows.Input.RelayCommand' does not exist in the implementation but it does exist in the contract. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.DependencyProperty System.Windows.Markup.XmlAttributeProperties.XmlSpaceProperty' changed from '[LocalizabilityAttribute(17)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.NeverLocalize)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Markup.XmlAttributeProperties.GetXmlNamespaceMaps(System.Windows.DependencyObject)' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.Markup.DesignerSerializationOptionsAttribute' on 'System.Windows.Markup.XmlAttributeProperties.GetXmlnsDefinition(System.Windows.DependencyObject)' changed from '[DesignerSerializationOptionsAttribute(1)]' in the contract to '[DesignerSerializationOptionsAttribute(DesignerSerializationOptions.SerializeAsAttribute)]' in the implementation. @@ -310,4 +343,4 @@ CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVi CannotChangeAttribute : Attribute 'System.Windows.Markup.DesignerSerializationOptionsAttribute' on 'System.Windows.Markup.XmlAttributeProperties.GetXmlSpace(System.Windows.DependencyObject)' changed from '[DesignerSerializationOptionsAttribute(1)]' in the contract to '[DesignerSerializationOptionsAttribute(DesignerSerializationOptions.SerializeAsAttribute)]' in the implementation. CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerSerializationVisibilityAttribute' on 'System.Windows.Media.Animation.Storyboard.GetTarget(System.Windows.DependencyObject)' changed from '[DesignerSerializationVisibilityAttribute(0)]' in the contract to '[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]' in the implementation. CannotChangeAttribute : Attribute 'System.Windows.LocalizabilityAttribute' on 'System.Windows.Shapes.Shape' changed from '[LocalizabilityAttribute(0, Readability=0)]' in the contract to '[LocalizabilityAttribute(LocalizationCategory.None, Readability=Readability.Unreadable)]' in the implementation. -Total Issues: 311 +Total Issues: 344 diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj index 334dae90a44..522c6a62e0a 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/PresentationFramework.csproj @@ -415,8 +415,12 @@ + + + + diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextBox.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextBox.cs index 059e93671ad..8ad50e725d9 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextBox.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/TextBox.cs @@ -97,6 +97,8 @@ public TextBox() : base() // TextBox only accepts plain text, so change TextEditor's default to that. this.TextEditor.AcceptsRichContent = false; + + SetValue(TemplateButtonCommandProperty, new RelayCommand(OnTemplateButtonClick)); } #endregion Constructors @@ -963,8 +965,168 @@ public Typography Typography } } + /// + /// Gets or sets displayed . + /// + public IconElement Icon + { + get => (IconElement)GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + /// + /// Defines which side the icon should be placed on. + /// + public ElementPlacement IconPlacement + { + get => (ElementPlacement)GetValue(IconPlacementProperty); + set => SetValue(IconPlacementProperty, value); + } + + public KeyboardNavigation keyboardNavigation { get; set; } + + /// + /// Gets or sets numbers pattern. + /// + public string PlaceholderText + { + get => (string)GetValue(PlaceholderTextProperty); + set => SetValue(PlaceholderTextProperty, value); + } + + /// + /// Gets or sets a value determining whether to display the placeholder. + /// + public bool PlaceholderEnabled + { + get => (bool)GetValue(PlaceholderEnabledProperty); + set => SetValue(PlaceholderEnabledProperty, value); + } + + /// + /// Gets or sets a value determining whether to enable the clear button. + /// + public bool ClearButtonEnabled + { + get => (bool)GetValue(ClearButtonEnabledProperty); + set => SetValue(ClearButtonEnabledProperty, value); + } + + /// + /// Gets or sets a value determining whether to show the clear button when is focused. + /// + public bool ShowClearButton + { + get => (bool)GetValue(ShowClearButtonProperty); + protected set => SetValue(ShowClearButtonProperty, value); + } + + /// + /// TODO + /// + public bool IsTextSelectionEnabled + { + get => (bool)GetValue(IsTextSelectionEnabledProperty); + set => SetValue(IsTextSelectionEnabledProperty, value); + } + + /// + /// Command triggered after clicking the button. + /// + public IRelayCommand TemplateButtonCommand => (IRelayCommand)GetValue(TemplateButtonCommandProperty); + #endregion Public Properties + //------------------------------------------------------ + // + // Static Properties + // + //------------------------------------------------------ + + #region Static properties + + /// + /// Property for . + /// + public static readonly DependencyProperty IconProperty = DependencyProperty.Register( + nameof(Icon), + typeof(IconElement), + typeof(TextBox), + new PropertyMetadata(null, null, IconSourceElementConverter.ConvertToIconElement) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty IconPlacementProperty = DependencyProperty.Register( + nameof(IconPlacement), + typeof(ElementPlacement), + typeof(TextBox), + new PropertyMetadata(ElementPlacement.Left) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty PlaceholderTextProperty = DependencyProperty.Register( + nameof(PlaceholderText), + typeof(string), + typeof(TextBox), + new PropertyMetadata(String.Empty) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty PlaceholderEnabledProperty = DependencyProperty.Register( + nameof(PlaceholderEnabled), + typeof(bool), + typeof(TextBox), + new PropertyMetadata(true) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty ClearButtonEnabledProperty = DependencyProperty.Register( + nameof(ClearButtonEnabled), + typeof(bool), + typeof(TextBox), + new PropertyMetadata(true) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register( + nameof(ShowClearButton), + typeof(bool), + typeof(TextBox), + new PropertyMetadata(false) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty IsTextSelectionEnabledProperty = DependencyProperty.Register( + nameof(IsTextSelectionEnabled), + typeof(bool), + typeof(TextBox), + new PropertyMetadata(false) + ); + + /// + /// Property for . + /// + public static readonly DependencyProperty TemplateButtonCommandProperty = DependencyProperty.Register( + nameof(TemplateButtonCommand), + typeof(IRelayCommand), + typeof(TextBox), + new PropertyMetadata(null) + ); + + #endregion + //------------------------------------------------------ // // Protected Methods @@ -1272,6 +1434,75 @@ internal override void OnScrollChanged(object sender, ScrollChangedEventArgs e) } } + /// + protected override void OnTextChanged(TextChangedEventArgs e) + { + base.OnTextChanged(e); + + if (PlaceholderEnabled && Text.Length > 0) + PlaceholderEnabled = false; + + if (!PlaceholderEnabled && Text.Length < 1) + PlaceholderEnabled = true; + + RevealClearButton(); + } + + /// + protected override void OnGotFocus(RoutedEventArgs e) + { + base.OnGotFocus(e); + + CaretIndex = Text.Length; + + RevealClearButton(); + } + + /// + protected override void OnLostFocus(RoutedEventArgs e) + { + base.OnLostFocus(e); + + HideClearButton(); + } + + /// + /// Reveals the clear button by property. + /// + protected void RevealClearButton() + { + if (ClearButtonEnabled && IsKeyboardFocusWithin) + ShowClearButton = Text.Length > 0; + } + + /// + /// Hides the clear button by property. + /// + protected void HideClearButton() + { + if (ClearButtonEnabled && !IsKeyboardFocusWithin && ShowClearButton) + ShowClearButton = false; + } + + /// + /// Triggered when the user clicks the clear text button. + /// + protected virtual void OnClearButtonClick() + { + if (Text.Length > 0) + Text = string.Empty; + } + + /// + /// Triggered by clicking a button in the control template. + /// + protected virtual void OnTemplateButtonClick(string parameter) + { + System.Diagnostics.Debug.WriteLine($"INFO: {typeof(TextBox)} button clicked", "Wpf.Ui.TextBox"); + + OnClearButtonClick(); + } + // this method is called by an editable ComboBox to raise a TextChanged event after // ComboBox.Text is changed outside the scope of a TextBox.Text change // (e.g. when an IME text composition has completed). It's a courtesy to diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ElementPlacement.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ElementPlacement.cs new file mode 100644 index 00000000000..2868c81a8a8 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/ElementPlacement.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Windows +{ + /// + /// Decides where to put the element. + /// + public enum ElementPlacement + { + /// + /// Puts the control element on the left. + /// + Left, + + /// + /// Puts the control element on the right. + /// + Right + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand.cs new file mode 100644 index 00000000000..7eeb8b40883 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Windows.Input +{ + /// + /// An interface expanding with the ability to raise + /// the event externally. + /// + public interface IRelayCommand : ICommand + { + /// + /// Notifies that the property has changed. + /// + void NotifyCanExecuteChanged(); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand{T}.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand{T}.cs new file mode 100644 index 00000000000..71bcb3b5f15 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/IRelayCommand{T}.cs @@ -0,0 +1,32 @@ +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Windows.Input; + +/// +/// A generic interface representing a more specific version of . +/// +/// The type used as argument for the interface methods. +public interface IRelayCommand : IRelayCommand +{ + /// + /// Provides a strongly-typed variant of . + /// + /// The input parameter. + /// Whether or not the current command can be executed. + /// Use this overload to avoid boxing, if is a value type. + bool CanExecute(T parameter); + + /// + /// Provides a strongly-typed variant of . + /// + /// The input parameter. + /// Use this overload to avoid boxing, if is a value type. + void Execute(T parameter); +} diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/RelayCommand{T}.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/RelayCommand{T}.cs new file mode 100644 index 00000000000..3068246fc9a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Input/RelayCommand{T}.cs @@ -0,0 +1,191 @@ +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT. +// Copyright (C) Leszek Pomianowski and WPF UI Contributors. +// All Rights Reserved. + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This file is inspired from the MvvmLight library (lbugnion/MvvmLight) + +using System.Runtime.CompilerServices; + +namespace System.Windows.Input; + +/// +/// A generic command whose sole purpose is to relay its functionality to other +/// objects by invoking delegates. The default return value for the CanExecute +/// method is . This class allows you to accept command parameters +/// in the and callback methods. +/// +/// The type of parameter being passed as input to the callbacks. +public class RelayCommand : IRelayCommand +{ + /// + /// The to invoke when is used. + /// + private readonly Action _execute; + + /// + /// The optional action to invoke when is used. + /// + private readonly Predicate _canExecute; + + /// + public event EventHandler CanExecuteChanged; + + /// + /// Initializes a new instance of the class that can always execute. + /// + /// The execution logic. + /// + /// Due to the fact that the interface exposes methods that accept a + /// nullable parameter, it is recommended that if is a reference type, + /// you should always declare it as nullable, and to always perform checks within . + /// + /// Thrown if is . + public RelayCommand(Action execute) + { + if (execute is null) + { + throw new ArgumentNullException(nameof(execute)); + } + + _execute = execute; + } + + /// + /// Initializes a new instance of the class. + /// + /// The execution logic. + /// The execution status logic. + /// See notes in . + /// Thrown if or are . + public RelayCommand(Action execute, Predicate canExecute) + { + if (execute is null) + { + throw new ArgumentNullException(nameof(execute)); + } + + if (canExecute is null) + { + throw new ArgumentNullException(nameof(canExecute)); + } + + _execute = execute; + _canExecute = canExecute; + } + + /// + public void NotifyCanExecuteChanged() + { + CanExecuteChanged.Invoke(this, EventArgs.Empty); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool CanExecute(T parameter) + { + if (_canExecute is null) + return false; + return _canExecute.Invoke(parameter) != false; + } + + /// + public bool CanExecute(object parameter) + { + // Special case a null value for a value type argument type. + // This ensures that no exceptions are thrown during initialization. + if (parameter is null && default(T) is not null) + { + return false; + } + + if (!TryGetCommandArgument(parameter, out T result)) + { + ThrowArgumentExceptionForInvalidCommandArgument(parameter); + } + + return CanExecute(result); + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Execute(T parameter) + { + _execute(parameter); + } + + /// + public void Execute(object parameter) + { + if (!TryGetCommandArgument(parameter, out T result)) + { + ThrowArgumentExceptionForInvalidCommandArgument(parameter); + } + + Execute(result); + } + + /// + /// Tries to get a command argument of compatible type from an input . + /// + /// The input parameter. + /// The resulting value, if any. + /// Whether or not a compatible command argument could be retrieved. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool TryGetCommandArgument(object parameter, out T result) + { + // If the argument is null and the default value of T is also null, then the + // argument is valid. T might be a reference type or a nullable value type. + if (parameter is null && default(T) is null) + { + result = default; + + return true; + } + + // Check if the argument is a T value, so either an instance of a type or a derived + // type of T is a reference type, an interface implementation if T is an interface, + // or a boxed value type in case T was a value type. + if (parameter is T argument) + { + result = argument; + + return true; + } + + result = default; + + return false; + } + + /// + /// Throws an if an invalid command argument is used. + /// + /// The input parameter. + /// Thrown with an error message to give info on the invalid parameter. + internal static void ThrowArgumentExceptionForInvalidCommandArgument(object parameter) + { + [MethodImpl(MethodImplOptions.NoInlining)] + static Exception GetException(object parameter) + { + if (parameter is null) + { + return new ArgumentException( + $"Parameter \"{nameof(parameter)}\" (object) must not be null, as the command type requires an argument of type {typeof(T)}.", + nameof(parameter) + ); + } + + return new ArgumentException( + $"Parameter \"{nameof(parameter)}\" (object) cannot be of type {parameter.GetType()}, as the command type requires an argument of type {typeof(T)}.", + nameof(parameter) + ); + } + + throw GetException(parameter); + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Win11/Styles/TextBox.xaml b/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Win11/Styles/TextBox.xaml new file mode 100644 index 00000000000..a157dae21e1 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/Themes/PresentationFramework.Win11/Styles/TextBox.xaml @@ -0,0 +1,362 @@ + + + + + 1,1,1,0 + 0,0,0,1 + 10,0,0,0 + 0,0,10,0 + 0,0,4,0 + 0,0,0,0 + 24 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +