zoukankan      html  css  js  c++  java
  • TextBox自定义控件

    首先来一发图:

    今天主要说的textBox内部给予提示:

    使用自定义控件方式:TextBoxTip继承TextBox

    利用TextBox的背景画刷功能

    VisualBrush是一种比较特殊的笔刷,它的功能仍然是用来给元素填充图案,但它的内容却可以是各种控件。

    你可以将其理解为一个普通的容器,但在其内部的所有控件都会失去交互能力,而只保留显示能力。

                                        <TextBox.Background>
                                            <VisualBrush Stretch="None" AlignmentX="Left">
                                                <VisualBrush.Transform>
                                                    <TranslateTransform X="5" Y="0"/>
                                                </VisualBrush.Transform>
                                                <VisualBrush.Visual>
                                                    <TextBlock x:Name="PART_EmptyText" Grid.Column="0" Text="{TemplateBinding TooTipText}" 
                                                FontSize="12"   Visibility="Collapsed" Foreground="{TemplateBinding Foreground}"  
                                                       Focusable="False"/>
                                                </VisualBrush.Visual>
                                            </VisualBrush>
                                        </TextBox.Background>

    在背景色上给予一个画刷,使用textBlock来显示要提示的文本。

    使用条件触发控制画刷的显示与隐藏:

                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding Path=IsFocused,ElementName=PART_Text}" Value="False"/>
                                    <Condition Binding="{Binding Path=Text,ElementName=PART_Text}" Value=""/>
                                </MultiDataTrigger.Conditions>
                                <Setter TargetName="PART_EmptyText" Property="Visibility" Value="Visible"/>
                            </MultiDataTrigger>

    当TextBox失去焦点和文本内容为“”等两个条件成立时 画刷显示。

    文本内部还放置了一个Button用于Clear

                            <Button  Grid.Column="1" 
                                     x:Name="Xbtn"
                                     ToolTip="Clear"
                                     Visibility="{TemplateBinding XButtonVisibility}"
                                     VerticalAlignment="Center" Margin="7 0"
                                     Command="{x:Static local:TextBoxTip.XButtonCommand}"
                                     Style="{StaticResource XCloseButton}"/>

    给Button注册Command事件

            /// <summary>
            /// Since we're using RoutedCommands for the increase/decrease commands, we need to
            /// register them with the command manager so we can tie the events
            /// to callbacks in the control.
            /// </summary>
            private static void InitializeCommands()
            {
                XButtonCommand = new RoutedCommand("XButtonCommand", typeof(TextBoxTip));
                CommandManager.RegisterClassCommandBinding(typeof(TextBoxTip),
                      new CommandBinding(XButtonCommand, CloseButtonCommand));
            }
    
            public static void CloseButtonCommand(Object sender, ExecutedRoutedEventArgs e)
            {
                TextBoxTip control = sender as TextBoxTip;
                if (control != null)
                {
                    control.Text = "";
                }
            }
    
            public static RoutedCommand XButtonCommand { set; get; }
    View Code

    同理:TextBoxSign也继承TextBox

    不过该模板中放置了两个TextBox,一个用于显示正常的数据,比如文本为:如果个性签名很长的话就会自定计算长度是否超过文本width,然后给予截取字符串显示省略号(...)

    一个用于显示截取后的文本内容,ShowTip的方式是采用上面画刷方式就不再多介绍了。

    关于动态计算是重写了文本Size方法,然后在方法内部使用一个根据字体,字号,字体风格,字体填充方式计算

       protected override Size ArrangeOverride(Size arrangeBounds)
            {
                Size size = base.ArrangeOverride(arrangeBounds);
                if (NormalIsFocus == false)
                {
                    ControlTrimming(arrangeBounds.Width);
                }
                return size;
            }
            private void ControlTrimming(double width)
            {
                if (!string.IsNullOrEmpty(this.Text))
                {
                    NormalTxt.Visibility = Visibility.Hidden;
                    TrimmingTxt.Visibility = Visibility.Visible;
                    Typeface face = new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch);
                    bool IsShowTip = false;
                    TrimmingTxt.Text = TrimmingHelper.Trim(Text, "...", "", width - 10, face, this.FontSize, ref IsShowTip);
                    Console.WriteLine(IsShowTip);
                    ShowToolTip(IsShowTip);
                }
            }

    如下图所示:width-10是为了提前10个宽度就要显示省略号:(减去10是为了解决 刚好文本长度填满整个文本时不显示省略号,临界值)

    完整代码如下:

    样式Xaml

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TipPlugs">
    
        <Style x:Key="XCloseButton" TargetType="{x:Type Button}">
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="Height" Value="10"/>
            <Setter Property="Width" Value="10"/>
            <Setter Property="ToolTip" Value="X"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid >
                            <Path x:Name="mPath" Data="M2.859125,1.4685 L1.4217499,2.889875 3.5625651,5.015809 1.4682621,7.1103131 2.8748757,8.5319866 4.9848079,6.4375335 7.111161,8.5628746 8.5181325,7.1407751 6.3768616,5.0154436 8.5341407,2.8744748 7.1115867,1.4523758 4.9855734,3.624328 z" Fill="White" Stretch="Fill" Margin="0.203" Stroke="#FFFFA1A1" Visibility="Collapsed"/>
                            <Path x:Name="nPath" Data="M2.859125,1.4685 L1.4217499,2.889875 3.5625651,5.015809 1.4682621,7.1103131 2.8748757,8.5319866 4.9848079,6.4375335 7.111161,8.5628746 8.5181325,7.1407751 6.3768616,5.0154436 8.5341407,2.8744748 7.1115867,1.4523758 4.9855734,3.624328 z" Fill="#4C666666" Stretch="Fill" Margin="0.203" Stroke="{x:Null}"/>
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"  Visibility="Collapsed"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsFocused" Value="True"/>
                            <Trigger Property="IsDefaulted" Value="True"/>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Visibility" TargetName="nPath" Value="Collapsed"/>
                                <Setter Property="Visibility" TargetName="mPath" Value="Visible"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True"/>
                            <Trigger Property="IsEnabled" Value="False"/>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        
        <!--Tip-->
        <Style TargetType="{x:Type local:TextBoxTip}">
            <Setter Property="TopBrush" Value="{DynamicResource TextBoxTopBrush}"/>
            <Setter Property="BorderBrush" Value="{DynamicResource TextBoxBorder}"/>
            <Setter Property="Background" Value="{DynamicResource TextBoxBackground}"/>
            <Setter Property="XButtonVisibility" Value="Collapsed"/>
            <Setter Property="Foreground" Value="LightGray"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="Height" Value="26"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:TextBoxTip}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition Width="Auto" />
                            </Grid.ColumnDefinitions>
                            <Rectangle x:Name="OuterglowRect" Visibility="Collapsed"
                                       Grid.ColumnSpan="2"
                                       RadiusX="2" RadiusY="2" Stroke="{DynamicResource OuterBlueBrush}"  StrokeThickness="1.5" />
                            <Border x:Name="Bd" SnapsToDevicePixels="True" 
                                    CornerRadius="2"  Margin="1"
                                    Grid.ColumnSpan="2"
                                    Background="{TemplateBinding Background}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}">
                            </Border>
                            <TextBox x:Name="PART_Text" Grid.Column="0" 
                                         BorderThickness="0"
                                         Style="{x:Null}"
                                         Padding="2,2"
                                         VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                         HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                         IsReadOnly="{Binding IsReadOnly,Mode=TwoWay,
                                         UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                         Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                                    RelativeSource={RelativeSource TemplatedParent}}">
                                <TextBox.Background>
                                    <VisualBrush Stretch="None" AlignmentX="Left">
                                        <VisualBrush.Transform>
                                            <TranslateTransform X="5" Y="0"/>
                                        </VisualBrush.Transform>
                                        <VisualBrush.Visual>
                                            <TextBlock x:Name="PART_EmptyText" Grid.Column="0" Text="{TemplateBinding TooTipText}" 
                                                FontSize="12"   Visibility="Collapsed" Foreground="{TemplateBinding Foreground}"  
                                                       Focusable="False"/>
                                        </VisualBrush.Visual>
                                    </VisualBrush>
                                </TextBox.Background>
                            </TextBox>
                            <Rectangle x:Name="glowRect" Margin="2 2 2 0" 
                                       RadiusX="2" RadiusY="2" Stroke="{x:Null}" 
                                       SnapsToDevicePixels="true" StrokeThickness="0" 
                                       Grid.ColumnSpan="2"
                                       Fill="{TemplateBinding TopBrush}" Height="3" VerticalAlignment="Top" >
    
                            </Rectangle>
                            <Button  Grid.Column="1" 
                                     x:Name="Xbtn"
                                     ToolTip="Clear"
                                     Visibility="{TemplateBinding XButtonVisibility}"
                                     VerticalAlignment="Center" Margin="7 0"
                                     Command="{x:Static local:TextBoxTip.XButtonCommand}"
                                     Style="{StaticResource XCloseButton}"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding Path=IsFocused,ElementName=PART_Text}" Value="False"/>
                                    <Condition Binding="{Binding Path=Text,ElementName=PART_Text}" Value=""/>
                                </MultiDataTrigger.Conditions>
                                <Setter TargetName="PART_EmptyText" Property="Visibility" Value="Visible"/>
                            </MultiDataTrigger>
    
                            <!--<MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding Path=IsReadOnly}" Value="True"/>
                                    <Condition Binding="{Binding Path=Text,ElementName=PART_Text}" Value=""/>
                                </MultiDataTrigger.Conditions>
                                <Setter TargetName="PART_EmptyText" Property="Visibility" Value="Visible"/>
                            </MultiDataTrigger>-->
    
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="BorderBrush" Value="Transparent"/>
                                <Setter TargetName="OuterglowRect" Property="Visibility" Value="Visible"/>
                            </Trigger>
                            <Trigger Property="IsReadOnly" Value="True">
                                <Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource TextBoxBorderRead}"/>
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource TextBoxBgRead}"/>
                                <Setter Property="Visibility" TargetName="glowRect" Value="Collapsed"/>
                            </Trigger>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding Path=Text,ElementName=PART_Text}" Value=""/>
                                </MultiDataTrigger.Conditions>
                                <Setter Property="Visibility" TargetName="Xbtn" Value="Collapsed"/>
                            </MultiDataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
    
        </Style>
    
        <!-- Sign TextBox-->
        <local:TextBoxConverter x:Key="EmptyConverter"/>
        <Style TargetType="{x:Type local:TextBoxSign}">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="FocusVisualStyle"  Value="{x:Null}"></Setter>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:TextBoxSign}">
    
                        <Border x:Name="OutBorder" BorderThickness="1"  CornerRadius="2" SnapsToDevicePixels="True">
                            <Border x:Name="InnerBorder"
                                    CornerRadius="2" SnapsToDevicePixels="True"
                                    Background="{TemplateBinding Background}"
                                    Padding="{TemplateBinding Padding}"
                                    BorderBrush="{TemplateBinding BorderBrush}"
                                    BorderThickness="{TemplateBinding BorderThickness}">
                                <Grid>
                                    <TextBox x:Name="PART_Text" Grid.Column="0" 
                                            BorderThickness="0"
                                            Style="{x:Null}"
                                            FocusVisualStyle="{x:Null}"
                                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                            IsReadOnly="{Binding IsReadOnly,Mode=TwoWay,
                                            UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=TemplatedParent}}"
                                            Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                                            RelativeSource={RelativeSource TemplatedParent}}">
                                        <TextBox.Background>
                                            <VisualBrush Stretch="None" AlignmentX="Left">
                                                <VisualBrush.Transform>
                                                    <TranslateTransform X="5" Y="0"/>
                                                </VisualBrush.Transform>
                                                <VisualBrush.Visual>
                                                    <TextBlock x:Name="PART_EmptyText" Grid.Column="0" Text="{TemplateBinding TooTipText}" 
                                                FontSize="12"   Visibility="Collapsed" Foreground="{TemplateBinding Foreground}"  
                                                       Focusable="False"/>
                                                </VisualBrush.Visual>
                                            </VisualBrush>
                                        </TextBox.Background>
                                    </TextBox>
                                    <TextBox x:Name="txbTrimming"
                                            Visibility="Hidden"
                                            BorderThickness="0"
                                            Style="{x:Null}"
                                            FocusVisualStyle="{x:Null}"
                                            Background="Transparent"
                                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                                            HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                                </Grid>
                            </Border>
                        </Border>
                        <ControlTemplate.Triggers>
    
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsFocused, ElementName=PART_Text}" Value="False"/>
                                    <Condition Binding="{Binding Text, ElementName=PART_Text,Converter={StaticResource EmptyConverter}}" Value=""/>
                                </MultiDataTrigger.Conditions>
                                <Setter TargetName="PART_EmptyText" Property="Visibility" Value="Visible"/>
                                <Setter TargetName="PART_Text" Property="Visibility" Value="Visible"/>
                            </MultiDataTrigger>
    
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsFocused, ElementName=PART_Text}" Value="True"/>
                                </MultiDataTrigger.Conditions>
                                <Setter TargetName="OutBorder" Property="BorderBrush" Value="Gray"/>
                                <Setter Property="Background" Value="White"  TargetName="InnerBorder"/>
                                <Setter Property="BorderBrush" Value="Transparent" TargetName="InnerBorder"/>
                                <Setter Property="BorderThickness" Value="0" TargetName="InnerBorder"/>
                            </MultiDataTrigger>
    
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsFocused, ElementName=PART_Text}" Value="False"/>
                                    <Condition Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=Self}}" Value="True"/>
                                </MultiDataTrigger.Conditions>
                                <Setter TargetName="OutBorder" Property="BorderBrush" Value="#7F353535"/>
                                <Setter Property="BorderBrush"  Value="#B2FFFFFF" TargetName="InnerBorder"/>
                                <Setter Property="Background" TargetName="InnerBorder">
                                    <Setter.Value>
                                        <LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
                                            <GradientStop Offset="0" Color="#A0FFFFFF"/>
                                            <GradientStop Offset="0.1" Color="#70FFFFFF"/>
                                            <GradientStop Offset="0.4" Color="#0CFFFFFF"/>
                                            <GradientStop Offset="0.5" Color="#00FFFFFF"/>
                                            <GradientStop Offset="0.6" Color="#0CFFFFFF"/>
                                            <GradientStop Offset="0.9" Color="#70FFFFFF"/>
                                            <GradientStop Offset="1" Color="#A0FFFFFF"/>
                                        </LinearGradientBrush>
                                    </Setter.Value>
                                </Setter>
                            </MultiDataTrigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    View Code

     TextBoxTip Code

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace TipPlugs
    {
        /// <summary>
        /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
        ///
        /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
        /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
        /// 元素中: 
        ///
        ///     xmlns:MyNamespace="clr-namespace:TextBoxTip"
        ///
        ///
        /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
        /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
        /// 元素中: 
        ///
        ///     xmlns:MyNamespace="clr-namespace:TextBoxTip;assembly=TextBoxTip"
        ///
        /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
        /// 并重新生成以避免编译错误: 
        ///
        ///     在解决方案资源管理器中右击目标项目,然后依次单击
        ///     “添加引用”->“项目”->[浏览查找并选择此项目]
        ///
        ///
        /// 步骤 2)
        /// 继续操作并在 XAML 文件中使用控件。
        ///
        ///     <MyNamespace:TextBoxTip/>
        ///
        /// </summary>
        public class TextBoxTip : TextBox
        {
            static TextBoxTip()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxTip), new FrameworkPropertyMetadata(typeof(TextBoxTip)));
                InitializeCommands();
            }
    
    
    
            protected override void OnTextChanged(TextChangedEventArgs e)
            {
                string text = this.Text;
                if (!string.IsNullOrEmpty(text) && IsShowXButton)
                {
                    XButtonVisibility = Visibility.Visible;
                }
                //else if (string.IsNullOrEmpty(text))
                //{
                //    XButtonVisibility = Visibility.Collapsed;
                //}
                base.OnTextChanged(e);
            }
    
            /// <summary>
            /// 提示文本,如:请输入用户名
            /// </summary>
            public string TooTipText
            {
                get { return (string)GetValue(TooTipTextProperty); }
                set { SetValue(TooTipTextProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for TootipText.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TooTipTextProperty =
                DependencyProperty.Register("TooTipText", typeof(string), typeof(TextBoxTip), new UIPropertyMetadata("", null));
    
    
            /// <summary>
            /// 三个像素描边颜色
            /// </summary>
            public Brush TopBrush
            {
                get { return (Brush)GetValue(TopBrushProperty); }
                set { SetValue(TopBrushProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for TopBrush.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TopBrushProperty =
                DependencyProperty.Register("TopBrush", typeof(Brush), typeof(TextBoxTip), new UIPropertyMetadata(null));
    
    
            /// <summary>
            /// 控制显示X按钮
            /// </summary>
            public Visibility XButtonVisibility
            {
                get { return (Visibility)GetValue(XButtonVisibilityProperty); }
                set { SetValue(XButtonVisibilityProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for XButtonVisibility.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty XButtonVisibilityProperty =
                DependencyProperty.Register("XButtonVisibility", typeof(Visibility), typeof(TextBoxTip),
                new UIPropertyMetadata(Visibility.Collapsed));
    
    
            /// <summary>
            ///  是否显示X按钮
            /// </summary>
            public bool IsShowXButton
            {
                get { return (bool)GetValue(IsShowXButtonProperty); }
                set { SetValue(IsShowXButtonProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for IsShowXButton.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty IsShowXButtonProperty =
                DependencyProperty.Register("IsShowXButton", typeof(bool), typeof(TextBoxTip), new UIPropertyMetadata(false));
    
    
            /// <summary>
            /// Since we're using RoutedCommands for the increase/decrease commands, we need to
            /// register them with the command manager so we can tie the events
            /// to callbacks in the control.
            /// </summary>
            private static void InitializeCommands()
            {
                XButtonCommand = new RoutedCommand("XButtonCommand", typeof(TextBoxTip));
                CommandManager.RegisterClassCommandBinding(typeof(TextBoxTip),
                      new CommandBinding(XButtonCommand, CloseButtonCommand));
            }
    
            public static void CloseButtonCommand(Object sender, ExecutedRoutedEventArgs e)
            {
                TextBoxTip control = sender as TextBoxTip;
                if (control != null)
                {
                    control.Text = "";
                }
            }
    
            public static RoutedCommand XButtonCommand { set; get; }
        }
    }
    View Code

    TextBoxSign Code

    using Commons;
    using Commons.Helper;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace TipPlugs
    {
        /// <summary>
        /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
        ///
        /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
        /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
        /// 元素中: 
        ///
        ///     xmlns:MyNamespace="clr-namespace:TipPlugs"
        ///
        ///
        /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
        /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
        /// 元素中: 
        ///
        ///     xmlns:MyNamespace="clr-namespace:TipPlugs;assembly=TipPlugs"
        ///
        /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
        /// 并重新生成以避免编译错误: 
        ///
        ///     在解决方案资源管理器中右击目标项目,然后依次单击
        ///     “添加引用”->“项目”->[浏览查找并选择此项目]
        ///
        ///
        /// 步骤 2)
        /// 继续操作并在 XAML 文件中使用控件。
        ///
        ///     <MyNamespace:TextBoxSign/>
        ///
        /// </summary>
        public class TextBoxSign : TextBox
        {
            static TextBoxSign()
            {
    
                DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxSign), new FrameworkPropertyMetadata(typeof(TextBoxSign)));
            }
    
            TextBox NormalTxt;
            TextBox TrimmingTxt;
            public override void OnApplyTemplate()
            {
                base.OnApplyTemplate();
                NormalTxt = this.Template.FindName("PART_Text", this) as TextBox;
                TrimmingTxt = this.Template.FindName("txbTrimming", this) as TextBox;
                TrimmingTxt.GotFocus += new RoutedEventHandler(TrimmingTxt_GotFocus);
                NormalTxt.LostFocus += new RoutedEventHandler(NormalTxt_LostFocus);
                NormalTxt.GotFocus += new RoutedEventHandler(NormalTxt_GotFocus);
                this.KeyUp += TextBoxSign_KeyUp;
            }
    
            private void TextBoxSign_KeyUp(object sender, KeyEventArgs e)
            {
                if (e.Key == Key.Enter)
                {
                    //FocusManager.SetFocusedElement(this, null);
                    //Keyboard.Focus(null);
                    NormalTxt_LostFocus(null, null);
                }
            }
    
            void NormalTxt_GotFocus(object sender, RoutedEventArgs e)
            {
                NormalIsFocus = true;
            }
    
            protected override void OnTextChanged(TextChangedEventArgs e)
            {
                bool IsShow = false;
                if (!string.IsNullOrEmpty(this.Text))
                {
                    IsShow = true;
                }
                else
                {
                    IsShow = false;
                }
                ShowToolTip(IsShow);
                base.OnTextChanged(e);
            }
    
            /// <summary>
            /// 如何显示Tooltip文本
            /// </summary>
            /// <param name="isShow"></param>
            private void ShowToolTip(bool isShow)
            {
                if (isShow)
                {
                    this.ToolTip = this.Text;
                }
                else
                {
                    this.ToolTip = null;
                }
            }
    
            void NormalTxt_LostFocus(object sender, RoutedEventArgs e)
            {
                if (!string.IsNullOrEmpty(this.Text))
                {
                    double wd = this.ActualWidth;
                    ControlTrimming(wd);
                }
                NormalIsFocus = false;
            }
    
            bool NormalIsFocus = false;
            void TrimmingTxt_GotFocus(object sender, RoutedEventArgs e)
            {
                if (!string.IsNullOrEmpty(this.Text))
                {
                    TrimmingTxt.Visibility = Visibility.Collapsed;
                    NormalTxt.Visibility = Visibility.Visible;
    
                }
                NormalTxt.Focus();
    
            }
    
            protected override Size ArrangeOverride(Size arrangeBounds)
            {
                Size size = base.ArrangeOverride(arrangeBounds);
                if (NormalIsFocus == false)
                {
                    ControlTrimming(arrangeBounds.Width);
                }
                return size;
            }
            private void ControlTrimming(double width)
            {
                if (!string.IsNullOrEmpty(this.Text))
                {
                    NormalTxt.Visibility = Visibility.Hidden;
                    TrimmingTxt.Visibility = Visibility.Visible;
                    Typeface face = new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch);
                    bool IsShowTip = false;
                    TrimmingTxt.Text = TrimmingHelper.Trim(Text, "...", "中回复哈市的范德萨发", width - 10, face, this.FontSize, ref IsShowTip);
                    Console.WriteLine(IsShowTip);
                    ShowToolTip(IsShowTip);
                }
            }
    
    
    
            /// <summary>
            /// 提示文本,如:请输入用户名
            /// </summary>
            public string TooTipText
            {
                get { return (string)GetValue(TooTipTextProperty); }
                set { SetValue(TooTipTextProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for TootipText.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty TooTipTextProperty =
                DependencyProperty.Register("TooTipText", typeof(string), typeof(TextBoxSign), new UIPropertyMetadata("", null));
        }
    
        class TextBoxConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
    
                return "";
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }
    View Code

    TrimmingHelper Code

    /***********************************************************************   
    * Copyright(c) 2016-2050 ligl
    * CLR 版本: 4.0.30319.42000   
    * 文 件 名:TrimmingHelper   
    * 创 建 人:ligl   
    * 创建日期:2016/7/14 21:05:16   
    * 修 改 人:ligl   
    * 修改日期:   
    * 备注描述:
    ************************************************************************/
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Windows.Media;
    
    namespace Commons.Helper
    {
        /// <summary>
        /// 计算长度是否超出文本宽度的帮助类
        /// </summary>
        public class TrimmingHelper
        {
    
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="source">原始文本</param>
            /// <param name="suffix">省略文本符号</param>
            /// <param name="endNoTrimSource">追加省略号后面的文本,source+endNoTrimSource总体长度计算省略号</param>
            /// <param name="width">文本长度</param>
            /// <param name="face">字体类</param>
            /// <param name="fontsize">字体大小</param>
            /// <param name="ShowTip">True标示截取了文本</param>
            /// <returns></returns>
            public static string Trim(string source, string suffix, string endNoTrimSource, double width, Typeface face, double fontsize, ref bool ShowTip)
            {
    
                if (face != null)
                {
                    //real display max width.
                    double realWidth = width;
    
                    //try to get GlyphTypeface.
                    GlyphTypeface glyphTypeface;
                    face.TryGetGlyphTypeface(out glyphTypeface);
    
                    if (glyphTypeface != null)
                    {
                        //calculate end string 's display width.
                        if (!string.IsNullOrEmpty(endNoTrimSource))
                        {
                            double notrimWidth = 0;
                            foreach (char c in endNoTrimSource)
                            {
                                ushort w;
                                glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
                                notrimWidth += glyphTypeface.AdvanceWidths[w] * fontsize;
                            }
    
                            realWidth = width - notrimWidth;
                        }
    
                        //calculate source 's screen width
                        double sourceWidth = 0;
                        if (!string.IsNullOrEmpty(source))
                        {
                            foreach (char c in source)
                            {
                                ushort w;
                                glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
                                sourceWidth += glyphTypeface.AdvanceWidths[w] * fontsize;
                            }
                        }
    
                        //don't need to trim.
                        if (sourceWidth <= realWidth) return source + endNoTrimSource;
    
                        //calculate suffix's display width
                        double suffixWidth = 0;
                        if (!string.IsNullOrEmpty(suffix))
                        {
                            foreach (char c in suffix)
                            {
                                ushort w;
                                glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
                                suffixWidth += glyphTypeface.AdvanceWidths[w] * fontsize;
                            }
                        }
    
                        realWidth = realWidth - suffixWidth;
    
                        if (realWidth > 0)
                        {
                            sourceWidth = 0;
                            string trimStr = string.Empty;
                            foreach (char c in source)
                            {
                                ushort w;
                                glyphTypeface.CharacterToGlyphMap.TryGetValue(c, out w);
    
                                double cWidth = glyphTypeface.AdvanceWidths[w] * fontsize;
    
                                if ((sourceWidth + cWidth) > realWidth)
                                {
                                    ShowTip = true;
                                    return trimStr + suffix + endNoTrimSource;
                                }
                                trimStr += c;
                                sourceWidth += cWidth;
                            }
                        }
                        else
                        {
                            ShowTip = true;
                            if (width > suffixWidth) return suffix;
                            else return "...";
    
                        }
                    }
                }
                ShowTip = false;
                return source + endNoTrimSource;
            }
        }
    }
    View Code

     使用方式:

    <UserControl x:Class="TipPlugs.UserControlTip"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:TipPlugs"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <UserControl.Resources>
            <!--ffffff 60%透明 6-1-->
            <SolidColorBrush x:Key="Brush61"  Color="#99FFFFFF"/>
    
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" x:Key="TopBdBrush">
                <GradientStop Color="#5B808080" Offset="0"/>
                <GradientStop Color="#19808080" Offset="1"/>
            </LinearGradientBrush>
    
            <SolidColorBrush x:Key="BdBrush" Color="#6643484B"></SolidColorBrush>
        </UserControl.Resources>
        <Grid>
            <StackPanel>
                <local:TextBoxTip 
                              VerticalContentAlignment="Top"
                              Background="{StaticResource Brush61}"
                              BorderBrush="{StaticResource BdBrush}"
                              TopBrush="{StaticResource TopBdBrush}"
                              Foreground="#FF7F7F7F"
                              IsShowXButton="True"
                               Width="200"   
                              HorizontalAlignment="Left"
                              TooTipText="输入关键字,回车进行搜索"          
                             x:Name="txtSearch"></local:TextBoxTip>
                <local:TextBoxSign x:Name="txbSignatrue" Text="{Binding Signature,Mode=TwoWay}"
                               HorizontalAlignment="Left"
                               TooTipText="编辑个性签名"  Height="22"  Width="200"      
                                 Margin="0,2"/>
            </StackPanel>
         
        </Grid>
    </UserControl>
    View Code

     源代码下载

  • 相关阅读:
    js正则表达式中的问号使用技巧总结
    380. Insert Delete GetRandom O(1)
    34. Find First and Last Position of Element in Sorted Array
    162. Find Peak Element
    220. Contains Duplicate III
    269. Alien Dictionary
    18. 4Sum
    15. 3Sum
    224. Basic Calculator
    227. Basic Calculator II
  • 原文地址:https://www.cnblogs.com/ligl/p/5674842.html
Copyright © 2011-2022 走看看