How to debug VisualStateManager in runtime
Asked Answered
O

2

17

There are very helpful tools out there to debug WPF applications in run-time like Snoop, WPF Inspector and Xaml Spy which allow you to sneak peek into running application and monitor property values, DataContext changes, routing events and even triggers switching.

But what I did not managed to find in any of them is the way how to monitor VisualStateManager (VSM) transitions between states on particular selected control in run-time.

Is there any tool that could help with figuring out why a control doesn't go into the particular expected state (considering absence of source code for this application/library)?

Update: The question is mostly about debugging compiled code, when you have no access to the source. For cases when you have access to source code here is pretty good explanation of one of the ways to go.

Overcash answered 26/7, 2013 at 13:9 Comment(4)
This is a good question. I think the only way is to make visual state manager as simple and thin as possible. Debugging UI stuff is a weak point of WPF. Therefore you might try to avoid it.Wellesz
@BillZhang - Yep, agree. And I certainly would like to avoid it if I could :/Overcash
for example you can put state transitions into event handler in code behind. Since these code are purely UI related it does not hurt and break any design patterns.Wellesz
@BillZhang, that may work, but only if you are authoring the code that deal with VisualStateManager. But what shall we do if the there is some third-party UI component with custom control that leverage VSM and it just not work as expected but is essential to application?Overcash
B
1

There are some reasons why a control does not transect its states.

There might be more than one VisualStateGroup and its has been named as something.

Calling a visual state before a control is loaded.

VisualState will be applied only after the control's OnApplyTemplate call.

if there are any syntax error.

How ever the Visual states are not able to tract with something but it can be debugged with the return value of GoToState method.

Hope this would helpful..

Baptistry answered 31/7, 2013 at 5:54 Comment(1)
Sankarann, thaks for answer. While this sounds correct, I'd rather looking for a tool (or kind of custom behavior/control that already exist) that could allow me to observe the current (VSM) state of the particular control in run-time, just like I can observe value of any of its properties with tools, mentioned in the question.Overcash
G
0

I has this issue because I added a "<ControlTemplate.Triggers>" section, so I had both "Style.Triggers" and "ControlTemplate.Triggers", it worked until I click on a column header, which generated the error "ExceptionObject {"La propriété '[Unknown]' ne pointe pas vers un DependencyObject du chemin '(0).(1)[1].(2)'."} object {System.InvalidOperationException}"

    <Style x:Key="GridViewColumnHeaderNoResize" TargetType="GridViewColumnHeader">
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Foreground" Value="{DynamicResource SolidColorBrushW1}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="GridViewColumnHeader">
                <Grid MinHeight="35">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Panel.Background).
                (GradientBrush.GradientStops)[1].(GradientStop.Color)"
                                            Storyboard.TargetName="HeaderBorder">
                                        <EasingColorKeyFrame KeyTime="0" Value="{StaticResource ControlMouseOverColor}" />
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed" />
                            <VisualState x:Name="Disabled" />
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="HeaderBorder" BorderThickness="0,1,0,1" Padding="2,0,2,0">
                        <Border.BorderBrush>
                            <LinearGradientBrush StartPoint="0,0"  EndPoint="0,1">
                                <LinearGradientBrush.GradientStops>
                                    <GradientStopCollection>
                                        <GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
                                        <GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" />
                                    </GradientStopCollection>
                                </LinearGradientBrush.GradientStops>
                            </LinearGradientBrush>
                        </Border.BorderBrush>
                        <Border.Background>

                            <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                <LinearGradientBrush.GradientStops>
                                    <GradientStopCollection>
                                        <GradientStop Color="{DynamicResource ColorN3}" Offset="0.0" />
                                        <GradientStop Color="{DynamicResource ColorN3}" Offset="1.0" />
                                    </GradientStopCollection>
                                </LinearGradientBrush.GradientStops>
                            </LinearGradientBrush>

                        </Border.Background>
                        <ContentPresenter x:Name="HeaderContent"
                          Margin="0,0,0,1"
                          RecognizesAccessKey="True"
                          VerticalAlignment="Center"
                          HorizontalAlignment="Stretch"                                              
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </Border>
                    <Thumb x:Name="PART_HeaderGripper" HorizontalAlignment="Right" Margin="0,0,-9,0" 
                                   Style="{StaticResource GridViewColumnHeaderGripper}" IsEnabled="False" />
                </Grid>
                
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Background" Value="{DynamicResource SolidColorBrushN4}" TargetName="HeaderBorder" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="Role" Value="Floating">
            <Setter Property="Opacity" Value="0" /> <!-- 0.7 -->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="GridViewColumnHeader">
                        <Canvas Name="PART_FloatingHeaderCanvas">
                            <Rectangle Fill="#60000000"
                     Width="{TemplateBinding ActualWidth}"
                     Height="{TemplateBinding ActualHeight}" />
                        </Canvas>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
        <Trigger Property="Role" Value="Padding">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="GridViewColumnHeader">
                        <Border Name="HeaderBorder" BorderThickness="0,1,0,1">
                            <Border.Background>
                                <SolidColorBrush Color="{DynamicResource ControlLightColor}" />
                            </Border.Background>
                            <Border.BorderBrush>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                    <LinearGradientBrush.GradientStops>
                                        <GradientStopCollection>
                                            <GradientStop Color="{DynamicResource BorderLightColor}" Offset="0.0" />
                                            <GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1.0" />
                                        </GradientStopCollection>
                                    </LinearGradientBrush.GradientStops>
                                </LinearGradientBrush>
                            </Border.BorderBrush>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter Property="Background" Value="{DynamicResource SolidColorBrushN4}"  />
        </Trigger>
    </Style.Triggers>
</Style>
Govan answered 9/12, 2022 at 9:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.