【WPF系列】Textbox

Style定义实例

给Textbox定义一个阴影效果。

<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
         <Setter Property="SnapsToDevicePixels" Value="True"/>
         <Setter Property="OverridesDefaultStyle" Value="True"/>
         <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
         <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
         <Setter Property="MinWidth" Value="120"/>
         <Setter Property="MinHeight" Value="20"/>
         <Setter Property="AllowDrop" Value="true"/>
         <Setter Property="Template">
            <Setter.Value>
               <ControlTemplate TargetType="{x:Type TextBoxBase}">
               <Border x:Name="Border"                                              
                     BorderThickness="1"
                     CornerRadius="2"
                     Padding="0">
                     <Border.BorderBrush>
                     <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
  <GradientStop Color="#888888" Offset="0" />
  <GradientStop Color="#AAAAAA" Offset=".2" />
</LinearGradientBrush>
                     </Border.BorderBrush>
                     <ScrollViewer x:Name="PART_ContentHost" Margin="0">
                        <ScrollViewer.Background>
                           <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                              <GradientStop Offset="0" Color="WhiteSmoke"/>
                              <GradientStop Offset="1" Color="LightGray"/>
                           </LinearGradientBrush>
                        </ScrollViewer.Background>
                     </ScrollViewer>
                  </Border>
                 
                  <ControlTemplate.Triggers>
                     <Trigger Property="IsEnabled" Value="False">
                        <Setter TargetName="Border" Property="Background" Value="#EEEEEE"/>
                        <Setter TargetName="Border" Property="BorderBrush" Value="#EEEEEE"/>
                        <Setter Property="Foreground" Value="#888888"/>
                     </Trigger>
                  </ControlTemplate.Triggers>
               </ControlTemplate>
            </Setter.Value>
         </Setter>
      </Style>

UpdateSourceTrigger

默认UpdateSourceTrigger为LostFoucs,有时需要及时CommitValue,则需要设置为PropertyChanged。这样当Text属性的值发生变化时,我们的值就能及时更新到Datasource中。

更多参考

How to: Control When the TextBox Text Updates the Source

NumberTextbox

  1. 使用NubmberTextboxBehavior
  2. 将TextBox的binding属性中Delay设置为1000
<Binding Path="UpperLeftCornerLatitude" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" Delay="1000">
</Binding>
//NumericTextBoxBehavior
/// <summary>
    /// This forces a TextBoxBase control to be numeric-entry only
    /// </summary>
    /// <example>
    /// <![CDATA[  <TextBox Cinch:NumericTextBoxBehavior.IsEnabled="True" />  ]]>
    /// </example>
    public static class NumericTextBoxBehavior
    {
        #region IsEnabled DP
        /// <summary>
        /// Dependency Property for turning on numeric behavior in a TextBox.
        /// </summary>
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached("IsEnabled",
                typeof(bool), typeof(NumericTextBoxBehavior),
                    new UIPropertyMetadata(false, OnEnabledStateChanged));

        /// <summary>
        /// Attached Property getter for the IsEnabled property.
        /// </summary>
        /// <param name="source">Dependency Object</param>
        /// <returns>Current property value</returns>
        public static bool GetIsEnabled(DependencyObject source)
        {
            return (bool)source.GetValue(IsEnabledProperty);
        }

        /// <summary>
        /// Attached Property setter for the IsEnabled property.
        /// </summary>
        /// <param name="source">Dependency Object</param>
        /// <param name="value">Value to set on the object</param>
        public static void SetIsEnabled(DependencyObject source, bool value)
        {
            source.SetValue(IsEnabledProperty, value);
        }

        /// <summary>
        /// This is the property changed handler for the IsEnabled property.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void OnEnabledStateChanged(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {
            TextBox tb = sender as TextBox;
            if (tb == null)
                return;

            tb.PreviewTextInput -= tbb_PreviewTextInput;
            DataObject.RemovePastingHandler(tb, OnClipboardPaste);

            bool b = ((e.NewValue != null && e.NewValue.GetType() == typeof(bool))) ?
                (bool)e.NewValue : false;
            if (b)
            {
                tb.PreviewTextInput += tbb_PreviewTextInput;
                DataObject.AddPastingHandler(tb, OnClipboardPaste);
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// This method handles paste and drag/drop events
        /// onto the TextBox. It restricts the character
        /// set to numerics and ensures we have consistent behavior.
        /// </summary>
        /// <param name="sender">TextBox sender</param>
        /// <param name="e">EventArgs</param>
        private static void OnClipboardPaste(object sender, DataObjectPastingEventArgs e)
        {
            TextBox tb = sender as TextBox;
            string text = e.SourceDataObject.GetData(e.FormatToApply) as string;

            if (tb != null && !string.IsNullOrEmpty(text) && !Validate(tb, text))
                e.CancelCommand();
        }

        /// <summary>
        /// This checks if the resulting string will match the regex expression
        /// </summary>
        static void tbb_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            TextBox tb = sender as TextBox;

            if (tb != null && !Validate(tb, e.Text))
                e.Handled = true;
        }

        #endregion

        private static bool Validate(TextBox tb, string newContent)
        {
            string testString = string.Empty;
            // replace selection with new text.
            if (!string.IsNullOrEmpty(tb.SelectedText))
            {
                string pre = tb.Text.Substring(0, tb.SelectionStart);
                string after = tb.Text.Substring(tb.SelectionStart + tb.SelectionLength,
                               tb.Text.Length - (tb.SelectionStart + tb.SelectionLength));
                testString = pre + newContent + after;
            }
            else
            {
                string pre = tb.Text.Substring(0, tb.CaretIndex);
                string after = tb.Text.Substring(tb.CaretIndex,
                                       tb.Text.Length - tb.CaretIndex);
                testString = pre + newContent + after;
            }

            Regex regExpr = new Regex(@"^([-+]?)(d*)([,.]?)(d*)$");
            if (regExpr.IsMatch(testString))
                return true;

            return false;
        }
    }

WaterMark/HintText/PlaceHoder

  1. 通过Style
  2. 通过AttachBehavior
  3. 通过自定义控件

1.给TextBox添加水印效果(提示文字)

<!--Add a placeHolder for TextBox using Tag value-->
    <Style x:Key="placeHolder" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Grid>
                        <TextBox Text="{Binding Path=Text,
                                                RelativeSource={RelativeSource TemplatedParent},
                                                Mode=TwoWay,
                                                UpdateSourceTrigger=PropertyChanged,
                                                Delay=1000}"
                                 x:Name="textSource"
                                 Background="Transparent"
                                 Panel.ZIndex="2" />
                        <TextBox Text="{TemplateBinding Tag}" Background="{TemplateBinding Background}" Panel.ZIndex="1">
                            <TextBox.Style>
                                <Style TargetType="{x:Type TextBox}">
                                    <Setter Property="Foreground" Value="Transparent" />
                                    <Style.Triggers>
                                        <DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}" Value="">
                                            <Setter Property="Foreground" Value="LightGray" />
                                        </DataTrigger>
                                    </Style.Triggers>
                                </Style>
                            </TextBox.Style>
                        </TextBox>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

2.通过AttachBehavior

3.通过自定义控件

    参考

    WPF validation rule preventing decimal entry in textbox?

    Set WPF Binding.StringFormat Property on TextBox via Style

    原文地址:https://www.cnblogs.com/HQFZ/p/4313001.html