如何使用自定义样式触发器在TextBox控件中绘制一条线

时间:2017-01-11 20:45:29

标签: c# wpf xaml

我有一个自定义文本框控件,我想在某个属性为true时绘制一条水平线,然后在属性为false时删除该行。该线的宽度必须是控制宽度的-2,并且距离控制底部的高度为-5。我目前正在使用带有以下OnRender的{​​{3}}来完成此行为:

protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
    base.OnRender(drawingContext);

    var rect = new Rect(AdornedElement.RenderSize);
    rect.Inflate(-2, -5);

    // ColoredPen is a custom class that holds a Pen object
    drawingContext.DrawLine(ColoredPen.Pen, rect.BottomLeft, rect.BottomRight);
}

我遇到了一些问题,其中Adorner没有正确刷新,因此即使相关属性为true,它也会消失。我已经尝试了几种不同的方法来确保Adorner的刷新,但它却失败了。我认为Adorner方法并不是解决我问题的正确方法。我认为如果我使用属性作为触发器的Adorner会更好。对于简单的示例,我们可以使用IsFocused属性。这是我到目前为止的代码,但我不确定如何设置Line的X和Y属性以及如何使其工作。这个当前的代码只是崩溃应用程序(是的,我知道在这段代码中设置的行的尺寸不是我想要的,这是我试图让线条出现,我想我可以从那里调整它)。

<Style x:Key="TextBoxUnderlineTemplate" TargetType="myUi:MyTextBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="myUi:MyTextBox">
                <Line Name="UnderlineStuff" Stroke="Black" X1="0"
                     X2="{Binding RelativeSource={RelativeSource Self}, Path=Width}"
                     Y1="{Binding RelativeSource={RelativeSource Self}, Path=Height}"
                     Y2="{Binding RelativeSource={RelativeSource Self}, Path=Height}"
                     StrokeThickness="2" Visibility="Collapsed"/>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsFocused" Value="True">
                        <Setter TargetName="UnderlineStuff" Property="Visibility" Value="Visible"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

所以,我正在寻找一种方法来使用ControlTemplate进行此工作,或者如果还有其他建议如何使这项工作,这也是可以接受的(Adorner已经出来)。请注意,一旦这个工作,我将需要添加一个比这一行稍低的第二行,具体取决于附加属性。

1 个答案:

答案 0 :(得分:1)

这会在IsMouseOver上显示下划线。您可能需要改进非常简单的转换器实现,它基于字体大小:

enter image description here

<强> XAML:

<Window x:Class="WpfApplication363.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication363"
    mc:Ignorable="d"
    Title="MainWindow" Height="300" Width="300">

<Window.Resources>

    <local:MyConverter x:Key="conv1"/>

    <SolidColorBrush x:Key="TextBox.Static.Border" Color="#FFABAdB3"/>
    <SolidColorBrush x:Key="TextBox.MouseOver.Border" Color="#FF7EB4EA"/>
    <SolidColorBrush x:Key="TextBox.Focus.Border" Color="#FF569DE5"/>

    <Style x:Key="TextBoxStyle1" TargetType="{x:Type TextBox}">
        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
        <Setter Property="BorderBrush" Value="{StaticResource TextBox.Static.Border}"/>
        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="AllowDrop" Value="true"/>
        <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <Grid>
                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                        </Border>
                        <Line x:Name="line1" 
                              Y1="{TemplateBinding FontSize, Converter={StaticResource conv1}}" 
                              X2="{Binding ElementName=border, Path=ActualWidth}" 
                              Y2="{TemplateBinding FontSize, Converter={StaticResource conv1}}" 
                              Stroke="Red" 
                              Visibility="Hidden"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Opacity" TargetName="border" Value="0.56"/>
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="true">
                            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.MouseOver.Border}"/>
                            <Setter Property="Visibility" TargetName="line1" Value="Visible"/>
                        </Trigger>
                        <Trigger Property="IsKeyboardFocused" Value="true">
                            <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource TextBox.Focus.Border}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsInactiveSelectionHighlightEnabled" Value="true"/>
                    <Condition Property="IsSelectionActive" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
            </MultiTrigger>
        </Style.Triggers>
    </Style>

</Window.Resources>

<Grid>

    <TextBox Style="{DynamicResource TextBoxStyle1}" 
             HorizontalAlignment="Center" 
             VerticalAlignment="Center" 
             FontSize="24"
             Text="Textbox with underline !"/>

</Grid>

<强>转换器:

public class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((double)value) + 4;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}