gpt4 book ai didi

wpf - VisualStateManager-集中控制时显示鼠标悬停状态

转载 作者:行者123 更新时间:2023-12-02 06:00:57 27 4
gpt4 key购买 nike

我正在使用Windows 8样式(以前称为Metro)创建WPF按钮。

我希望按钮的焦点状态显示为纯色背景。当鼠标悬停在控件上时,我希望背景稍微变暗以创建可以单击按钮的视觉提示。

不幸的是,我在下面编写的XAML无法正常工作。焦点状态正确显示,但是当鼠标悬停在控件上时,背景不会像我希望的那样变暗。

<Color x:Key="DoxCycleGreen">
#FF8DC63F
</Color>

<!-- Soft Interface : DoxCycle Green -->
<Color x:Key="DoxCycleGreenSoft">
#FFC0DC8F
</Color>

<Style x:Key="MetroButton" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Focused">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreenSoft}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor" Storyboard.TargetProperty="Color" To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor" Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>


<Grid Background="Transparent" >
<Border BorderThickness="1,1,1,1" Padding="2">
<Border.BorderBrush>
<SolidColorBrush x:Name="BorderColor" Color="{StaticResource DoxCycleGreen}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name="BackgroundColor" Color="White"/>
</Border.Background>

<ContentPresenter
x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content">
<TextBlock.Foreground>
<SolidColorBrush x:Name="FontColor" Color="{StaticResource DoxCycleGreen}"/>
</TextBlock.Foreground>
</ContentPresenter>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

最佳答案

现在,我已经测试了您的代码。您在这里遇到了几个问题。但是主要问题是WPF控件一次只能处于特定状态组的一个可视状态。 在像您到达此处的情况下,控件既可以集中控制又可以移到鼠标上,WPF必须选择要应用的州(由于两个州都在同一州组中,因此不能同时应用这两个州)。因此,在这种情况下,它只是将其保持在Focused状态,而不是将其发送到MouseOver状态。

如果每个控件处于不同的状态组,则控件可以处于多个状态。从this documentation:

Each VisualStateGroup contains a collection of VisualState objects that are mutually exclusive. That is, the control is always in exactly one state of in each VisualStateGroup.



因此,我们纠正此代码的第一步是包括适当的状态组,该状态组将使按钮能够显示其Focused状态,然后显示其MouseOver状态(其他可能性可以通过此更改来纠正,但这就是您注意到的那个特别是您以前的方法没有做到的)。

为此,我们需要小心地命名我们的状态组,尤其是正确地命名我们的状态名。这是因为Button类内部的代码可能会进行类似于 VisualStateManager.GoToState(this, "VerySpecificStateName", true);的调用(我没有检查Button类的实际源代码来验证这一点,但是在需要启动状态更改的地方编写了自定义控件,我知道一定是那样的东西。为了获得我们需要的状态组和状态名称的列表,我们可以使用Expression Blend来“编辑”控制模板的副本(它将为我们填充所需的状态),或者找到它们 here 。该文档向我们展示了我们需要一个名为“FocusStates”的状态组以及该组中的两个状态“Focused”和“Unfocused”(以及其他状态组和状态)。顺便说一句,为了说明Button类如何通过这些特定的命名状态来启动其状态更改,如果您通过将“Focus”状态名称替换为“MisspelledFocus”来更改原始代码,则会看到您的按钮从不输入状态。

实现第一个更改,我们可能会得到如下结果:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor" Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<!-- Focus States -->
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreenSoft}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

这在某种程度上解决了问题。但是,如果您在Expression Blend中查看此内容,则会在状态组标题中看到一条警告:

之所以收到此警告,是因为我们要在多个状态组中更改同一属性/对象对的值-在这种情况下,该属性/对象对的名称是“BackgroundColor”的“Color”属性。为什么这可能是个问题?因为我之前说过-如果一个控件处于不同的状态组中,则该控件可以一次处于多个状态。因此,如果用户已赋予按钮焦点并且用户也将鼠标悬停在按钮上,则WPF对于应应用哪个动画可能会模棱两可,因为这两种状态都表示要对相同的精确属性进行动画处理,但使用不同的方式。

同样,此第一个更改并没有完全为我们提供我们想要的东西。如果您尝试为按钮提供焦点,然后将鼠标悬停在它上面,则它的正确位置从“正常”变为“焦点”,再到“MouseOver”。但是,如果现在停止悬停,您将看到该按钮不会返回其“焦点”状态。

您可以使用多种方法来解决此问题,并实现与您想要的目标类似的功能,但仅作为示例,我们可以这样做。 (这可能不是最干净的实现,但是它解决了常见的对象/属性问题。):
<Color x:Key="DoxCycleGreen">
#FF8DC63F
</Color>

<SolidColorBrush x:Key="DoxCycleGreenBrush" Color="{StaticResource DoxCycleGreen}" />

<!-- Soft Interface : DoxCycle Green -->
<Color x:Key="DoxCycleGreenSoft">
#FFC0DC8F
</Color>

<SolidColorBrush x:Key="DoxCycleGreenSoftBrush" Color="{StaticResource DoxCycleGreenSoft}" />

<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="White" Duration="0:0:0.150" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="MouseOverBorder">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BackgroundColor"
Storyboard.TargetProperty="Color"
To="Transparent" Duration="0:0:0.150" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color"
To="{StaticResource DoxCycleGreen}" Duration="0:0:0.150" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="BorderColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
<ColorAnimation Storyboard.TargetName="FontColor"
Storyboard.TargetProperty="Color" To="DarkGray" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<!-- Focus States -->
<VisualStateGroup x:Name="FocusStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.15"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Focused">
<Storyboard>

<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="FocusBorder">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="ContentSiteWhiteForeground">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>


<Grid Background="Transparent" >
<Border x:Name="BaseBorder" BorderThickness="1,1,1,1">
<Border.BorderBrush>
<SolidColorBrush x:Name="BorderColor" Color="{StaticResource DoxCycleGreen}"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush x:Name="BackgroundColor" Color="White"/>
</Border.Background>
</Border>
<Border x:Name="FocusBorder"
BorderThickness="1,1,1,1"
Background="{DynamicResource DoxCycleGreenSoftBrush}"
Opacity="0" />

<Border x:Name="MouseOverBorder"
BorderThickness="1,1,1,1"
Background="{DynamicResource DoxCycleGreenBrush}"
Opacity="0" />

<ContentPresenter
x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content" Margin="2">
<TextBlock.Foreground>
<SolidColorBrush x:Name="FontColor" Color="{StaticResource DoxCycleGreen}"/>
</TextBlock.Foreground>
</ContentPresenter>

<ContentPresenter
x:Name="ContentSiteWhiteForeground"

VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Content" Margin="2" Opacity="0">
<TextBlock.Foreground>
<SolidColorBrush Color="White" />
</TextBlock.Foreground>
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

现在您将看到我们已经消除了WPF的歧义。而且我们看到它现在可以处理状态从“正常”更改为“焦点”再更改为“MouseOver”再正确返回到“焦点”的情况。

关于wpf - VisualStateManager-集中控制时显示鼠标悬停状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14632796/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com