我正在尝试使用ControlTemplate中的ControlTemplate作为ToggleButton。我希望ToggleButton在选中时看上去是一种方式,而在未选中时则是另一种方式。当ToggleButton被禁用时,我也希望它看起来不同。我遇到的问题是,未经检查的VisualState似乎超过了禁用的VisualState。
文档指出:“每个VisualStateGroup包含一个相互排斥的VisualState对象集合。”不错,但是团体之间的相互排他性呢?
不管怎样,这是我的ControlTemplate。如何让TextBlock对这三种状态使用不同的颜色:选中、未检查和禁用?
<Style x:Key="GraphToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="Pink" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="#3AA5DB" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="TextBlock" To="Green" Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" CornerRadius="4" Background="{TemplateBinding Background}">
<StackPanel>
<TextBlock Name="TextBlock" FontFamily="/Resources/#Entypo" Text="" FontSize="87" Foreground="#909090" HorizontalAlignment="Center" Margin="0,-25,0,0" />
<TextBlock FontFamily="Proxima Nova Rg" Text="Stimulator" FontSize="18" Foreground="{StaticResource BlackBrush}" HorizontalAlignment="Center" Margin="0,12,0,0" />
</StackPanel>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>发布于 2014-10-23 04:26:14
每个VisualStateGroup包含一个相互排斥的VisualState对象集合。
这其实是真的。但是,还有一个要求,即每个VisualState 都不应该影响相同的属性。在这种情况下,未检查状态和禁用状态会影响相同元素的相同属性Foreground。
所以我不认为我们能有任何优雅的解决方案。我们只有这样的工作(事实上,这是在WPF中的样式元素时常用的)。我们需要一些名为DisabledTextBlock的假元素,这应该与原始元素TextBlock放在同一个网格中。一旦禁用状态出现,就应该显示该假元素并隐藏原始元素,并隐藏Unchecked (或Checked)状态的所有效果,并将Disabled的效果带到最前面。以下是工作代码:
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<!-- unchanged -->
</VisualStateGroup>
<VisualStateGroup x:Name="CommonStates">
<VisualState Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="DisabledTextBlock" To="1" Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Border" CornerRadius="4" Background="{TemplateBinding Background}">
<StackPanel>
<Grid>
<TextBlock Name="TextBlock" FontFamily="/Resources/#Entypo" Text=""
FontSize="87" Foreground="#909090" HorizontalAlignment="Center"
Margin="0,-25,0,0" Background="Transparent"/>
<!-- the fake element -->
<TextBlock Name="DisabledTextBlock" Opacity="0"
FontFamily="{Binding FontFamily, ElementName=TextBlock}"
Text="{Binding Text,ElementName=TextBlock}"
FontSize="{Binding FontSize,ElementName=TextBlock}"
Foreground="Pink" HorizontalAlignment="Center"
Margin="{Binding Margin, ElementName=TextBlock}"
Background="Transparent"
FontStyle="{Binding FontStyle,ElementName=TextBlock}"
FontWeight="{Binding FontSize, ElementName=TextBlock}"/>
</Grid>
<TextBlock FontFamily="Proxima Nova Rg" Text="Stimulator" FontSize="18"
Foreground="Black" HorizontalAlignment="Center" Margin="0,12,0,0"/>
</StackPanel>
</Border>
</Border>
</ControlTemplate>您可能有一些新的要求,但这里的想法是明确的。我想这是唯一的解决办法。
https://stackoverflow.com/questions/26520661
复制相似问题