I'm working with a custom RadioButton
control that is allows the user to give a rating between 1 and 5 depending on the selected RadioButton
.
However, there are times in my application that the 5 RadioButtons
are disabled, and then re-enabled. When this happens the VisualState
for the Checked RadioButton
doesn't activate. Instead, all 5 RadioButtons
appear as the Normal state.
Why is this happening? How can I resolve this?
Here is the example of the RadioButtons
that I'm using.
If I start by selecting the first group of 5 RadioButtons
, and make a selection, then everything may appear as the above image does.
But, if I select the second group of 5 RadioButtons
, my control is designed so that the first group will disable. This works fine, and the second group enables properly. After that, if I select the first group again, every Radiobutton
will appear with the Normal VisualState. This is a problem, because my program knows that behind the scenes that #1 is still Checked. The Checked VisualState is NOT triggered, so it looks something like this:
The goal here is that the Checked VisualState
will be resumed as it appears in the first image.
Here is the corresponding XAML code for the VisualStates
:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState Name="Normal"/>
<VisualState Name="Disabled">
<Storyboard>
<ColorAnimation Storyboard.TargetName="FillBrush" Storyboard.TargetProperty="Color" To="#FFEEEEEE" Duration="0"/>
<ColorAnimation Storyboard.TargetName="StrokeBrush" Storyboard.TargetProperty="Color" To="#FF777777" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="MoodEllipse" Storyboard.TargetProperty="StrokeThickness" To="1" Duration="0"/>
<ColorAnimation Storyboard.TargetName="Presenter" Storyboard.TargetProperty="(TextBlock.Foreground).Color" To="#FF777777" Duration="0"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState Name="Checked">
<Storyboard>
<ParallelTimeline>
<ColorAnimation Storyboard.TargetName="FillBrush" Storyboard.TargetProperty="Color" To="#FFC5F5FF" Duration="0:0:0.05"/>
<ColorAnimation Storyboard.TargetName="StrokeBrush" Storyboard.TargetProperty="Color" To="#FF12394F" Duration="0:0:0.05"/>
<DoubleAnimation Storyboard.TargetName="MoodEllipse" Storyboard.TargetProperty="StrokeThickness" To="2" Duration="0:0:0.05"/>
</ParallelTimeline>
</Storyboard>
</VisualState>
<VisualState Name="Unchecked"/>
<VisualState Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
This XAML code seems to be in accordance to how to use VisualStates
, but I suppose there must be something wrong with it.
I've referenced these pages:
- Customizing the Appearance of an Existing Control by Creating a ControlTemplate
- RadioButton Styles and Templates
As some additional notes, I've noticed that the Checked VisualState
can be triggered if I click one of the Unchecked RadioButtons
. At this point, everything is works properly --until the group of RadioButtons
is disabled & re-enabled.
Also, I've experience even stranger behavior for the Checked VisualState
when I didn't include the empty Unchecked VisualState
in the above XAML code.
Any insight about why the VisualStates
are behaving strangely would be greatly appreciated. Thanks much!
EDIT:
I'm not sure if it matters, but the group of RadioButtons
are disabled because they are in StackPanels
whose IsEnabled
property is bound to the outside RadioButton
's IsChecked
property:
<StackPanel IsEnabled="{Binding RelativeSource={RelativeSource AncestorType={x:Type RadioButton}}, Path=IsChecked}">
Apparently, the problem is that I am using the same target properties within two different VisualStateGroups
, yet I'm not sure why this causes the problem.
In order to have the desired affect, which is to display the Checked behavior after re-enabling, I created another Ellipse
which is overlaid of the the original Ellipse
.
The original Ellipse
is fully opaque and it's Fill/Stroke properties are modified by the CheckStates group ONLY.
The new Ellipse
is initially fully transparent (Opacity="0"
), but the Disabled state causes the opacity to change to fully opaque.
This new Ellipse
fades into into view and covers up the original Ellipse
, which is showing the appearance of the Checked/Unchecked states. This causes the overall result of the RadioButton
to appear Disabled.
This fixed the problem describe in the OP, but it introduces a new issue: the transition from the Disabled state to the Checked state is immediate. This can be resolve by including this VisualTransition
in the CommonStates group:
<VisualTransition From="Disabled" To="Checked" GeneratedDuration="0:0:0.25"/>
Here is the final XAML used to solve the problem:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="Disabled" To="Checked" GeneratedDuration="0:0:0.25"/>
</VisualStateGroup.Transitions>
<VisualState Name="Normal"/>
<VisualState Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="EllipseOverlay" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.15"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState Name="Checked">
<Storyboard>
<ParallelTimeline>
<ColorAnimation Storyboard.TargetName="FillBrush" Storyboard.TargetProperty="Color" To="#FFC5F5FF" Duration="0:0:0.05"/>
<ColorAnimation Storyboard.TargetName="StrokeBrush" Storyboard.TargetProperty="Color" To="#FF12394F" Duration="0:0:0.05"/>
<DoubleAnimation Storyboard.TargetName="MoodEllipse" Storyboard.TargetProperty="StrokeThickness" To="2" Duration="0:0:0.05"/>
</ParallelTimeline>
</Storyboard>
</VisualState>
<VisualState Name="Unchecked"/>
<VisualState Name="Indeterminate"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
In my control, I have this Ellipse
appear after my original Ellipse
, causing the new one to appear on top when the opacity increases. Below is the new Ellipse
:
<Ellipse x:Name="EllipseOverlay" StrokeThickness="1" Opacity="0" Fill="#FFEEEEEE" Stroke="#FF777777"/>
Note that this Ellipse
contains the Fill/Stroke properties that were using the the OP's Disabled VisualState
.
来源:https://stackoverflow.com/questions/25801126/checked-visualstate-is-not-triggered-after-radiobutton-is-re-enabled