如何在运行时调试VisualStateManager

17

有一些非常有用的工具可以在运行时调试WPF应用程序,例如Snoop, WPF InspectorXaml Spy,它们允许您窥视正在运行的应用程序并监视属性值、DataContext更改、路由事件甚至触发器切换。

但是我没有在它们中任何一个找到的是如何在运行时监视特定选定控件上的VisualStateManager(VSM)状态转换的方法。

是否有任何工具可以帮助确定为什么控件不进入特定预期状态(考虑到此应用程序/库没有源代码)?

更新:这个问题主要是关于调试已编译的代码,当你没有源代码访问权限时。对于你源代码访问权限的情况,这里有一个相当不错的解释其中介绍了一种方法。


2
这是一个很好的问题。我认为唯一的方法是尽可能地使可视化状态管理器简单而轻量化。调试 UI 相关的东西是 WPF 的一个弱点。因此,你可能会尝试避免它。 - Bill Zhang
@BillZhang - 是的,同意。如果可以的话,我肯定想避免它 :/ - Sevenate
1
例如,您可以将状态转换放入代码后台的事件处理程序中。由于这些代码纯粹与UI相关,因此不会损害或破坏任何设计模式。 - Bill Zhang
@BillZhang,这可能有效,但前提是编写的代码涉及VisualStateManager。但如果有一些使用VSM的定制控件的第三方UI组件不能按预期工作,但对应用程序至关重要,我们该怎么办? - Sevenate
2个回答

1

有一些原因导致控件无法转换其状态。

可能有多个VisualStateGroup,并且已被命名为某个名称。

在控件加载之前调用视觉状态。

VisualState仅在控件的OnApplyTemplate调用后应用。

如果存在任何语法错误。

然而,视觉状态无法与某些东西跟踪,但可以通过GoToState方法的返回值进行调试。

希望这会有所帮助。


1
Sankarann,感谢您的回答。虽然这听起来是正确的,但我更想寻找一个工具(或已经存在的自定义行为/控件),它可以让我在运行时观察特定控件的当前(VSM)状态,就像我可以使用问题中提到的工具观察其任何属性的值一样。 - Sevenate

0
我遇到了这个问题,因为我添加了一个 "<ControlTemplate.Triggers>" 部分,所以我既有 "Style.Triggers" 也有 "ControlTemplate.Triggers"。它一直有效,直到我单击列标题时,就会出现错误 " 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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接