wpf - 使用视觉状态管理器设置前景时出现问题

标签 wpf templates vsm

我有一个 WPF 应用程序,我正在尝试使用 .Net v4 视觉状态管理器设置 TextBox 的样式。具体来说,我尝试设置 MouseOver 状态的前景和背景的颜色。

所发生的情况是,虽然背景和边框发生了完美的变化,但前景却没有。如果我使用的画笔通过 StaticResource 获取颜色,则前景根本不会改变。如果我使用的画笔通过 DynamicResource 获取颜色,那么当我将鼠标悬停在文本框上时,所有文本框的前景都会发生变化。显然,要么我做错了什么,要么我想做的事根本不可能用 VSM 实现(这会相当令人失望)。

以下是我正在使用的资源:

<Color x:Key="ControlBackgroundColor" R="178" G="178" B="178" A="255" />
<Color x:Key="ControlForegroundColor" R="0" G="0" B="0" A="255" />
<Color x:Key="BorderColor" R="127" G="127" B="127" A="255" />
<Color x:Key="MouseOverControlBackgroundColor" R="0" G="0" B="0" A="255" />
<Color x:Key="MouseOverControlForegroundColor" R="255" G="255" B="255" A="255" />
<Color x:Key="MouseOverBorderColor" R="178" G="178" B="178" A="255" />

<SolidColorBrush PresentationOptions:Freeze="True" x:Key="ControlBackgroundBrush" Color="{DynamicResource ControlBackgroundColor}" />
<SolidColorBrush PresentationOptions:Freeze="True" x:Key="ControlForegroundBrush" Color="{DynamicResource ControlForegroundColor}" />
<SolidColorBrush PresentationOptions:Freeze="True" x:Key="BorderBrush" Color="{DynamicResource BorderColor}" />

<SolidColorBrush PresentationOptions:Freeze="True" x:Key="MouseOverControlBackgroundBrush" Color="{DynamicResource MouseOverControlBackgroundColor}" />
<SolidColorBrush PresentationOptions:Freeze="True" x:Key="MouseOverControlForegroundBrush" Color="{DynamicResource MouseOverControlForegroundColor}" />
<SolidColorBrush PresentationOptions:Freeze="True" x:Key="MouseOverBorderBrush" Color="{DynamicResource MouseOverBorderColor}" />

<Style TargetType="{x:Type TextBox}" >
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Padding" Value="2"/>
    <Setter Property="Margin" Value="1" />
    <Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}" />
    <Setter Property="Background" Value="{DynamicResource ControlBackgroundBrush}" />
    <Setter Property="Foreground" Value="{DynamicResource ControlForegroundBrush}" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TextBox">
                <Grid x:Name="RootElement">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimation Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" To="{DynamicResource MouseOverBorderColor}" Duration="0:0:0.3"/>
                                    <ColorAnimation Storyboard.TargetName="MouseOverBorder" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="{DynamicResource MouseOverControlBackgroundColor}" Duration="0:0:0.3"/>
                                    <ColorAnimation Storyboard.TargetName="PART_ContentHost" Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)" To="{DynamicResource MouseOverControlForegroundColor}" Duration="0:0:0.3"/>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1" Opacity="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
                        <Grid x:Name="ContentGrid">
                            <Border x:Name="MouseOverBorder" BorderThickness="1" BorderBrush="Transparent" Background="Transparent">
                                <ScrollViewer x:Name="PART_ContentHost" Padding="{TemplateBinding Padding}" Foreground="{TemplateBinding Foreground}" BorderThickness="0" IsTabStop="False"/>
                            </Border>
                        </Grid>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

令我感到非常奇怪的是,无论我使用静态还是动态资源,以完全相同的方式创建和动画的背景和边框画笔都可以完美地工作,但前景色却不然。

如果有人有任何想法,或者有更好的方法来做到这一点,我很乐意听到。

大卫·穆林 IMA技术

最佳答案

VisualStateManager 无法控制通过绑定(bind)设置值的属性。在您的示例中,BackgroundBorderBrush 均设置为本地值 (Transparent),因此 VSM 可以为它们设置动画。另一方面,Foreground 是使用 TemplateBinding 设置的,因此如果绑定(bind)值有效,VSM 将无法为其设置动画。

这是 VisualStateManager 的一般限制,您将在所有使用它的示例中看到它。解决该问题的典型策略是使用图层和不透明度来提供彩色动画的错觉,而实际上发生的是从一个元素到另一个元素的淡入淡出。这是有效的,因为您可以完全控制隐藏层,并且不必将其绑定(bind)到任何东西。不幸的是,这不能满足您的需求,因为该元素不是静态的;您不能有两个文本框。

最终的效果是,我认为您不能同时为文本前景色设置动画并允许用户指定前景色。

关于wpf - 使用视觉状态管理器设置前景时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3644969/

相关文章:

c# - 任务等待和线程终止导致内存泄漏

c++ - 检查模板函数是否存在

silverlight - ControlTemplate.Triggers Silverlight 3 中的 WPF 等效项

c++ - `class template Example<int>;` 语句对 C++11 意味着什么?

OpenGL 方差阴影贴图反向衰减

wpf - 动画 TranslateTransform.Y 到控件的高度(目的是将元素滑出视线)

wpf - 如何在 WPF DataGrid 中实现多列 ComboBox DataGridColumn?

c# - 触摸屏上的 WPF 模态对话框

c# - PropertyChangedEventHandler 是如何工作的?

c++在模板中使用元组作为参数包