浏览代码

Implement password char on TextBox rather than separate control.

Dan Walmsley 7 年之前
父节点
当前提交
aca0fb3eba

+ 2 - 1
samples/ControlCatalog/Pages/TextBoxPage.xaml

@@ -15,9 +15,10 @@
                  UseFloatingWatermark="True"
                  Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/>
 
-        <PasswordBox Width="200"
+        <TextBox Width="200"
                  Watermark="Password Box"
                  UseFloatingWatermark="True"
+                 PasswordChar="*"
                  Text="Password" />
         <TextBox Width="200" Text="Left aligned text" TextAlignment="Left" />
         <TextBox Width="200" Text="Center aligned text" TextAlignment="Center" />

+ 0 - 47
src/Avalonia.Controls/PasswordBox.cs

@@ -1,47 +0,0 @@
-using Avalonia.Controls.Primitives;
-using Avalonia.Styling;
-using System;
-
-namespace Avalonia.Controls
-{
-    public class PasswordBox : TextBox, IStyleable
-    {
-        Type IStyleable.StyleKey => typeof(PasswordBox);
-
-        public PasswordBox()
-        {
-            this.GetObservable(TextProperty).Subscribe(text =>
-            {
-                if (text != null)
-                {
-                    DisplayText = new string(PasswordChar, text.Length);
-                }
-                else
-                {
-                    DisplayText = null;
-                }
-            });
-        }
-
-        public static readonly StyledProperty<char> PasswordCharProperty = AvaloniaProperty.Register<PasswordBox, char>(nameof(PasswordChar), '*');
-
-        public char PasswordChar
-        {
-            get => GetValue(PasswordCharProperty);
-            set => SetValue(PasswordCharProperty, value);
-        }
-
-        public static readonly StyledProperty<string> DisplayTextProperty = AvaloniaProperty.Register<PasswordBox, string>(nameof(DisplayText));
-
-        public string DisplayText
-        {
-            get => GetValue(DisplayTextProperty);
-            set => SetValue(DisplayTextProperty, value);
-        }
-
-        protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
-        {
-            base.OnTemplateApplied(e);
-        }
-    }
-}

+ 35 - 5
src/Avalonia.Controls/TextBox.cs

@@ -30,7 +30,10 @@ namespace Avalonia.Controls
                 nameof(CaretIndex),
                 o => o.CaretIndex,
                 (o, v) => o.CaretIndex = v);
-        
+
+        public static readonly StyledProperty<char> PasswordCharProperty =
+            AvaloniaProperty.Register<TextBox, char>(nameof(PasswordChar));        
+
         public static readonly StyledProperty<bool> IsReadOnlyProperty =
             AvaloniaProperty.Register<TextBox, bool>(nameof(IsReadOnly));
 
@@ -53,6 +56,9 @@ namespace Avalonia.Controls
                 defaultBindingMode: BindingMode.TwoWay,
                 enableDataValidation: true);
 
+        public static readonly StyledProperty<string> DisplayTextProperty =
+            AvaloniaProperty.Register<TextBox, string>(nameof(DisplayText));
+
         public static readonly StyledProperty<TextAlignment> TextAlignmentProperty =
             TextBlock.TextAlignmentProperty.AddOwner<TextBox>();
 
@@ -78,7 +84,7 @@ namespace Avalonia.Controls
 
             public bool Equals(UndoRedoState other) => ReferenceEquals(Text, other.Text) || Equals(Text, other.Text);
         }
-
+        
         private string _text;
         private int _caretIndex;
         private int _selectionStart;
@@ -117,6 +123,18 @@ namespace Avalonia.Controls
                 horizontalScrollBarVisibility,
                 BindingPriority.Style);
             _undoRedoHelper = new UndoRedoHelper<UndoRedoState>(this);
+
+            this.GetObservable(TextProperty).Subscribe(text =>
+            {
+                if (PasswordChar != default(char))
+                {
+                    DisplayText = new string(PasswordChar, text.Length);
+                }
+                else
+                {
+                    DisplayText = Text;
+                }
+            });
         }
 
         public bool AcceptsReturn
@@ -147,7 +165,13 @@ namespace Avalonia.Controls
                     _undoRedoHelper.UpdateLastState();
             }
         }
-        
+
+        public char PasswordChar
+        {
+            get => GetValue(PasswordCharProperty);
+            set => SetValue(PasswordCharProperty, value);
+        }
+
         public bool IsReadOnly
         {
             get { return GetValue(IsReadOnlyProperty); }
@@ -208,6 +232,12 @@ namespace Avalonia.Controls
             }
         }
 
+        public string DisplayText
+        {
+            get => GetValue(DisplayTextProperty);
+            set => SetValue(DisplayTextProperty, value);
+        }
+
         public TextAlignment TextAlignment
         {
             get { return GetValue(TextAlignmentProperty); }
@@ -832,9 +862,9 @@ namespace Avalonia.Controls
         private void SetTextInternal(string value)
         {
             try
-            {
+            {                
                 _ignoreTextChanges = true;
-                SetAndRaise(TextProperty, ref _text, value);
+                SetAndRaise(TextProperty, ref _text, value);                
             }
             finally
             {

+ 0 - 64
src/Avalonia.Themes.Default/PasswordBox.xaml

@@ -1,64 +0,0 @@
-<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
-  <Style Selector="PasswordBox">
-    <Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}"/>
-    <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/>
-    <Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}"/>
-    <Setter Property="Padding" Value="4"/>
-    <Setter Property="Template">
-      <ControlTemplate>
-        <Border Name="border"
-                Background="{TemplateBinding Background}"
-                BorderBrush="{TemplateBinding BorderBrush}"
-                BorderThickness="{TemplateBinding BorderThickness}">
-          <DockPanel Margin="{TemplateBinding Padding}">
-            
-            <TextBlock Name="floatingWatermark"
-                       Foreground="{DynamicResource ThemeAccentBrush}"
-                       FontSize="{DynamicResource FontSizeSmall}"
-                       Text="{TemplateBinding Watermark}"
-                       DockPanel.Dock="Top">
-              <TextBlock.IsVisible>
-                <MultiBinding Converter="{x:Static BoolConverters.And}">
-                  <Binding RelativeSource="{RelativeSource TemplatedParent}"
-                           Path="UseFloatingWatermark"/>
-                  <Binding RelativeSource="{RelativeSource TemplatedParent}"
-                           Path="DisplayText"
-                           Converter="{x:Static StringConverters.NotNullOrEmpty}"/>
-                </MultiBinding>
-              </TextBlock.IsVisible>
-            </TextBlock>
-
-            <DataValidationErrors>
-              <ScrollViewer HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
-                            VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
-                
-                <Panel>
-                  <TextBlock Name="watermark"
-                             Opacity="0.5"
-                             Text="{TemplateBinding Watermark}"
-                             IsVisible="{TemplateBinding Path=Text, Converter={x:Static StringConverters.NullOrEmpty}}"/>
-                  <TextPresenter Name="PART_TextPresenter"
-                                 Text="{TemplateBinding Text, Mode=TwoWay}"
-                                 CaretIndex="{TemplateBinding CaretIndex}"
-                                 SelectionStart="{TemplateBinding SelectionStart}"
-                                 SelectionEnd="{TemplateBinding SelectionEnd}"
-                                 TextAlignment="{TemplateBinding TextAlignment}"
-                                 TextWrapping="{TemplateBinding TextWrapping}"/>
-                </Panel>
-              </ScrollViewer>
-            </DataValidationErrors>
-          </DockPanel>
-        </Border>
-      </ControlTemplate>
-    </Setter>
-  </Style>
-  <Style Selector="TextBox:pointerover /template/ Border#border">
-    <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderDarkBrush}"/>
-  </Style>
-  <Style Selector="TextBox:focus /template/ Border#border">
-    <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderDarkBrush}"/>
-  </Style>
-  <Style Selector="TextBox:error /template/ Border#border">
-    <Setter Property="BorderBrush" Value="{DynamicResource ErrorBrush}"/>
-  </Style>
-</Styles>

+ 2 - 2
src/Avalonia.Themes.Default/TextBox.xaml

@@ -38,12 +38,12 @@
                              Text="{TemplateBinding Watermark}"
                              IsVisible="{TemplateBinding Path=Text, Converter={x:Static StringConverters.NullOrEmpty}}"/>
                   <TextPresenter Name="PART_TextPresenter"
-                                 Text="{TemplateBinding Text, Mode=TwoWay}"
+                                 Text="{TemplateBinding DisplayText, Mode=TwoWay}"
                                  CaretIndex="{TemplateBinding CaretIndex}"
                                  SelectionStart="{TemplateBinding SelectionStart}"
                                  SelectionEnd="{TemplateBinding SelectionEnd}"
                                  TextAlignment="{TemplateBinding TextAlignment}"
-                                 TextWrapping="{TemplateBinding TextWrapping}"/>
+                                 TextWrapping="{TemplateBinding TextWrapping}"/>                                   
                 </Panel>
               </ScrollViewer>
             </DataValidationErrors>