Mahapps.Metro TextBox - ClearTextButton 自定义样式

Mahapps.Metro TextBox - ClearTextButton custom style

我正在开发我的第一个 WPF 应用程序,我决定使用 Mahapps.Metro 样式。 我的其中一个视图中有一个这样的文本框:

<TextBox x:Name="txtMy" Style="{StaticResource My_TxtBox}"
         Controls:TextBoxHelper.Watermark="My..." 
         Controls:TextBoxHelper.ClearTextButton="True"
         Grid.Row="1" Grid.Column="0" />

注:xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"

这是我的 TextBox 风格:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:MyApp.Resources.Styles">
    <Style x:Key="My_TxtBox" BasedOn="{StaticResource {x:Type TextBox}}" 
           TargetType="{x:Type TextBox}">
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="FontSize" Value="15" />
        <Setter Property="Height" Value="40" />
        <Setter Property="Margin" Value="4" />
        <Setter Property="Foreground" Value="White" />
        <Setter Property="Background">
            <Setter.Value>
                <SolidColorBrush Color="#232228" Opacity="0.6" />
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush">
            <Setter.Value>
                <SolidColorBrush Color="#1ABC9C" Opacity="0.6" />
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

现在,我的问题是:如何向 ClearTextButton 添加自定义样式,即我想在悬停或按下时更改 ClearTextButton 的背景颜色?我该怎么做?

我问这个是因为我在互联网上没有找到类似的东西。

提前致谢

您要实现的目标并非特定于 Mahapps。 您必须修改文本框模板才能实现此目的。

在模板中,您会看到一个 MouseOver 触发器,如下所示:

 <Trigger Property="IsMouseOver" Value="True">
    <Setter TargetName="Base" Property="BorderBrush" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Controls:ControlsHelper.MouseOverBorderBrush)}" />
 </Trigger>

只需为触发器内的背景添加额外的 setter。

 <Setter Property="Background" TargetName="Base" Value="Red"/>

另一种方法是覆盖文本框的默认 mahapps 样式。(这将影响项目中的所有文本框)。 将 Mahapps sources 添加到您的项目,然后在 MahApps.Metro/Styles/Controls.TextBox.xaml 中,您将看到必须修改的相同触发器。

您需要在控件模板中修改相应的触发器。

这是修改后的样式:

XAML:

    <SolidColorBrush x:Key="MyMouseOverBackground" Color="LightCoral"></SolidColorBrush>
    <SolidColorBrush x:Key="MyMouseOverForeground" Color="Red"></SolidColorBrush>
    <SolidColorBrush x:Key="MyPressedBackground" Color="LightBlue"></SolidColorBrush>
    <SolidColorBrush x:Key="MyPressedForeground" Color="Blue"></SolidColorBrush>

    <Style x:Key="TextBoxStyle1" TargetType="{x:Type TextBox}">
        <Setter Property="Height" Value="50"/>
        <Setter Property="Background" Value="{DynamicResource ControlBackgroundBrush}"/>
        <Setter Property="BorderBrush" Value="{DynamicResource TextBoxBorderBrush}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="CaretBrush" Value="{DynamicResource BlackBrush}"/>
        <Setter Property="ContextMenu" Value="{DynamicResource TextBoxMetroContextMenu}"/>
        <Setter Property="Controls:ControlsHelper.FocusBorderBrush" Value="{DynamicResource TextBoxFocusBorderBrush}"/>
        <Setter Property="Controls:ControlsHelper.MouseOverBorderBrush" Value="{DynamicResource TextBoxMouseOverBorderBrush}"/>
        <Setter Property="Controls:TextBoxHelper.ButtonFontSize" Value="{DynamicResource ClearTextButtonFontSize}"/>
        <Setter Property="Controls:TextBoxHelper.ButtonWidth" Value="22"/>
        <Setter Property="Controls:TextBoxHelper.IsMonitoring" Value="True"/>
        <Setter Property="FontFamily" Value="{DynamicResource ContentFontFamily}"/>
        <Setter Property="FontSize" Value="{DynamicResource ContentFontSize}"/>
        <Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
        <Setter Property="MinHeight" Value="26"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="SelectionBrush" Value="{DynamicResource HighlightBrush}"/>
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="enterGotFocus">
                            <DoubleAnimation Duration="0:0:0.2" To="0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                        </Storyboard>
                        <Storyboard x:Key="exitGotFocus">
                            <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                        </Storyboard>
                        <Storyboard x:Key="enterHasText">
                            <DoubleAnimation Duration="0:0:0.2" From="0.2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                        </Storyboard>
                        <Storyboard x:Key="exitHasText">
                            <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <Grid>
                        <AdornerDecorator x:Name="PART_WaitingForDataEffectAdornerDecorator" Visibility="Collapsed">
                            <AdornerDecorator.CacheMode>
                                <BitmapCache EnableClearType="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </AdornerDecorator.CacheMode>
                            <Border x:Name="PART_WaitingForDataEffectGrid" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </AdornerDecorator>
                        <Border x:Name="Base" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        <Grid x:Name="PART_InnerGrid" Margin="2">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition x:Name="TextColumn" Width="*"/>
                                <ColumnDefinition x:Name="ButtonColumn" Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition x:Name="ButtonRow" Height="*"/>
                            </Grid.RowDefinitions>
                            <ScrollViewer x:Name="PART_ContentHost" BorderThickness="0" Background="{x:Null}" Grid.Column="0" IsTabStop="False" Margin="2" Grid.Row="1" VerticalAlignment="Stretch"/>
                            <TextBlock x:Name="PART_Message" Grid.Column="0" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="False" Margin="6,2" Opacity="0.6" Padding="{TemplateBinding Padding}" Grid.Row="1" TextAlignment="{TemplateBinding Controls:TextBoxHelper.WatermarkAlignment}" Text="{TemplateBinding Controls:TextBoxHelper.Watermark}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            <ContentControl x:Name="PART_FloatingMessageContainer" Grid.ColumnSpan="2" Grid.Column="0" Grid.Row="0" Style="{DynamicResource FloatingMessageContainerStyle}">
                                <TextBlock x:Name="PART_FloatingMessage" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Style="{DynamicResource MetroAutoCollapsingTextBlock}" TextAlignment="{TemplateBinding Controls:TextBoxHelper.WatermarkAlignment}" Text="{TemplateBinding Controls:TextBoxHelper.Watermark}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </ContentControl>
                            <Button x:Name="PART_ClearText" ContentTemplate="{TemplateBinding Controls:TextBoxHelper.ButtonContentTemplate}" Content="{TemplateBinding Controls:TextBoxHelper.ButtonContent}" Grid.Column="1" Foreground="{TemplateBinding Foreground}" Focusable="False" FontSize="{TemplateBinding Controls:TextBoxHelper.ButtonFontSize}" FontFamily="{TemplateBinding Controls:TextBoxHelper.ButtonFontFamily}" IsTabStop="False" Controls:TextBoxHelper.IsClearTextButtonBehaviorEnabled="{Binding (Controls:TextBoxHelper.ClearTextButton), Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" Grid.Row="0" Grid.RowSpan="2" Style="{DynamicResource ChromelessButtonStyle}" Width="{TemplateBinding Controls:TextBoxHelper.ButtonWidth}">
                                <Button.Visibility>
                                    <Binding Mode="OneWay" Path="(Controls:TextBoxHelper.ClearTextButton)" RelativeSource="{RelativeSource TemplatedParent}">
                                        <Binding.Converter>
                                            <BooleanToVisibilityConverter/>
                                        </Binding.Converter>
                                    </Binding>
                                </Button.Visibility>
                            </Button>
                        </Grid>
                        <Border x:Name="DisabledVisualElement" BorderBrush="{DynamicResource ControlsDisabledBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{DynamicResource ControlsDisabledBrush}" IsHitTestVisible="False" Opacity="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Visibility="{Binding (Controls:ControlsHelper.DisabledVisualElementVisibility), Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding (Controls:TextBoxHelper.ButtonsAlignment), RelativeSource={RelativeSource Self}}" Value="Left">
                            <Setter Property="Width" TargetName="ButtonColumn" Value="*"/>
                            <Setter Property="Grid.Column" TargetName="PART_ClearText" Value="0"/>
                            <Setter Property="Grid.Column" TargetName="PART_ContentHost" Value="1"/>
                            <Setter Property="Grid.Column" TargetName="PART_Message" Value="1"/>
                            <Setter Property="Width" TargetName="TextColumn" Value="Auto"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="">
                            <Setter Property="Visibility" TargetName="PART_Message" Value="Visible"/>
                        </DataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}" Value="True"/>
                                <Condition Binding="{Binding (Controls:TextBoxHelper.UseFloatingWatermark), RelativeSource={RelativeSource Self}}" Value="True"/>
                                <Condition Binding="{Binding (Controls:TextBoxHelper.HasText), RelativeSource={RelativeSource Self}}" Value="True"/>
                            </MultiDataTrigger.Conditions>
                            <MultiDataTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.2" From="0" To="15" Storyboard.TargetProperty="MaxHeight" Storyboard.TargetName="PART_FloatingMessageContainer">
                                            <DoubleAnimation.EasingFunction>
                                                <ExponentialEase EasingMode="EaseInOut" Exponent="2"/>
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>
                                        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_FloatingMessageContainer"/>
                                        <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)" Storyboard.TargetName="PART_FloatingMessage">
                                            <DoubleAnimation.EasingFunction>
                                                <ExponentialEase EasingMode="EaseOut" Exponent="2"/>
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiDataTrigger.EnterActions>
                            <MultiDataTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.2" From="15" To="0" Storyboard.TargetProperty="MaxHeight" Storyboard.TargetName="PART_FloatingMessageContainer">
                                            <DoubleAnimation.EasingFunction>
                                                <ExponentialEase EasingMode="EaseInOut" Exponent="2"/>
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>
                                        <DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_FloatingMessageContainer"/>
                                        <DoubleAnimation Duration="0:0:0.2" To="20" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.Y)" Storyboard.TargetName="PART_FloatingMessage">
                                            <DoubleAnimation.EasingFunction>
                                                <ExponentialEase EasingMode="EaseIn" Exponent="2"/>
                                            </DoubleAnimation.EasingFunction>
                                        </DoubleAnimation>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiDataTrigger.ExitActions>
                        </MultiDataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding (Controls:TextBoxHelper.ButtonsAlignment), RelativeSource={RelativeSource Self}}" Value="Right"/>
                                <Condition Binding="{Binding (Controls:TextBoxHelper.ClearTextButton), RelativeSource={RelativeSource Self}}" Value="False"/>
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Grid.ColumnSpan" TargetName="PART_ContentHost" Value="2"/>
                            <Setter Property="Grid.ColumnSpan" TargetName="PART_Message" Value="2"/>
                        </MultiDataTrigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="BorderBrush" TargetName="Base" Value="{Binding (Controls:ControlsHelper.MouseOverBorderBrush), RelativeSource={RelativeSource TemplatedParent}}"/>
                        </Trigger>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter Property="Opacity" TargetName="DisabledVisualElement" Value="0.6"/>
                        </Trigger>
                        <Trigger Property="IsReadOnly" Value="True">
                            <Setter Property="IsEnabled" TargetName="PART_ClearText" Value="False"/>
                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter Property="BorderBrush" TargetName="Base" Value="{Binding (Controls:ControlsHelper.FocusBorderBrush), RelativeSource={RelativeSource TemplatedParent}}"/>
                            <Setter Property="Foreground" TargetName="PART_FloatingMessage" Value="{DynamicResource AccentColorBrush}"/>
                            <Setter Property="Opacity" TargetName="PART_FloatingMessage" Value="1"/>
                        </Trigger>
                        <!--
                        <Trigger Property="IsMouseOver" SourceName="PART_ClearText" Value="True">
                            <Setter Property="Background" TargetName="PART_ClearText" Value="{DynamicResource GrayBrush8}"/>
                            <Setter Property="Foreground" TargetName="PART_ClearText" Value="{DynamicResource AccentColorBrush}"/>
                        </Trigger>
                        <Trigger Property="IsPressed" SourceName="PART_ClearText" Value="True">
                            <Setter Property="Background" TargetName="PART_ClearText" Value="{DynamicResource BlackBrush}"/>
                            <Setter Property="Foreground" TargetName="PART_ClearText" Value="{DynamicResource WhiteBrush}"/>
                        </Trigger>
                        -->
                        <Trigger Property="IsMouseOver" SourceName="PART_ClearText" Value="True">
                            <Setter Property="Background" TargetName="PART_ClearText" Value="{DynamicResource MyMouseOverBackground}"/>
                            <Setter Property="Foreground" TargetName="PART_ClearText" Value="{DynamicResource MyMouseOverForeground}"/>
                        </Trigger>
                        <Trigger Property="IsPressed" SourceName="PART_ClearText" Value="True">
                            <Setter Property="Background" TargetName="PART_ClearText" Value="{DynamicResource MyPressedBackground}"/>
                            <Setter Property="Foreground" TargetName="PART_ClearText" Value="{DynamicResource MyPressedForeground}"/>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="Controls:TextBoxHelper.HasText" Value="False"/>
                                <Condition Property="IsFocused" Value="True"/>
                            </MultiTrigger.Conditions>
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.2" To="0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <MultiTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.ExitActions>
                        </MultiTrigger>
                        <Trigger Property="Controls:TextBoxHelper.HasText" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.2" From="0.2" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Duration="0:0:0.2" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_Message"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsVisible" Value="True"/>
                                <Condition Property="Controls:TextBoxHelper.IsWaitingForData" Value="True"/>
                            </MultiTrigger.Conditions>
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation AutoReverse="True" Timeline.DesiredFrameRate="30" Duration="0:0:2" From="0" RepeatBehavior="Forever" To="1" Storyboard.TargetProperty="(Effect).Opacity" Storyboard.TargetName="PART_WaitingForDataEffectGrid"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <Setter Property="Visibility" TargetName="PART_WaitingForDataEffectAdornerDecorator" Value="Visible"/>
                            <Setter Property="Effect" TargetName="PART_WaitingForDataEffectGrid" Value="{DynamicResource WaitingForDataEffect}"/>
                        </MultiTrigger>
                        <Trigger Property="Controls:TextBoxHelper.IsWaitingForData" Value="False">
                            <Setter Property="Visibility" TargetName="PART_WaitingForDataEffectAdornerDecorator" Value="Collapsed"/>
                            <Setter Property="Effect" TargetName="PART_WaitingForDataEffectGrid" Value="{x:Null}"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ValidationErrorTemplate}"/>
    </Style>