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

     源代码下载

  • 相关阅读:
    用MFC(C++)实现拼音搜索
    MFC里ON_COMMAND_RANGE消息映射的ID问题
    01:MFC应用程序编程
    MFC笔记(DN)
    linuxmint系统定制与配置(2)-输入法
    linuxmint系统定制与配置(3)-字体
    linuxmint系统定制与配置(1)-系统初始配置
    笔记-读官方Git教程(2)~安装与配置
    笔记-读官方Git教程(1)~认识Git
    Python中多层List展平为一层
  • 原文地址:https://www.cnblogs.com/ligl/p/5674842.html
Copyright © 2011-2022 走看看