繁体   English   中英

如何刷新VisualStateManager的“聚焦” VisualState的样式效果?

[英]How to refresh style effects of 'Focused' VisualState of VisualStateManager?

我具有ListBoxItem的样式,如下所示,并且当listBoxItem保留在提到的VisualState中时,失去了“焦点”视觉效果的问题。 如何强制适当的视觉效果出现在“关注的” ListBoxItem上?

实现错误的场景:

1)单击ListBoxItem->它获得焦点和样式(确定)。

2)将指针移到该ListBoxItem上->它仍然聚焦并接收'MouseOver'的样式(如此处建议的,它位于单独的VisualStateGroup'CommonStates'中: https : //msdn.microsoft.com/zh-cn/library /system.windows.controls.listboxitem%28v=vs.95%29.aspx )(确定)。

3)使鼠标离开ListBoxItem的边界->它失去MouseOver(ok)的样式。

4)现在,ListBoxItem处于“ CommonStates”的“正常”状态,并且也是“关注”状态,但是没有针对“关注”的时尚外观(这是我的问题)。

5)尝试单击此ListBoxItem无效

您能给我一些建议,如何处理?

我正在使用Silverlight,所以禁止触发器4我。

这是我的风格:

    <Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="HorizontalAlignment" Value="Left" />
    <Setter Property="ContentControl.Foreground" Value="{StaticResource ViewModeButtonForeground}" />
    <Setter Property="Focusable" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Border x:Name="RootElement">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="(ContentControl.Foreground)">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ViewModeButtonForeground}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckOuterBorder" Storyboard.TargetProperty="BorderBrush">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ViewModeButtonOuterBorder_MouseOver}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckOuterBorder" Storyboard.TargetProperty="Background">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ViewModeButtonBackground_MouseOver}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="FocusStates">
                            <VisualState x:Name="Focused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="(ContentControl.Foreground)">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ViewModeButtonForeground_Focused}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckOuterBorder" Storyboard.TargetProperty="BorderBrush">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ViewModeButtonOuterBorder_Focused}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckOuterBorder" Storyboard.TargetProperty="Background">
                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="{StaticResource ViewModeButtonBackground_Normal}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Unfocused"></VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid>
                        <Border x:Name="CheckOuterBorder" CornerRadius="2" BorderThickness="1" BorderBrush="Transparent" Background="Transparent">
                        </Border>
                        <Grid x:Name="GridContent" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Width="Auto">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                                <ColumnDefinition Width="Auto"></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" HorizontalAlignment="Left" Source="{Binding ImgSource, Mode=OneWay}"/>
                            <ContentControl x:Name="Content" Grid.Column="1" Margin="3,0,0,0" Foreground="{TemplateBinding Foreground}" Content="{Binding Title}" ContentTemplate="{TemplateBinding ContentTemplate}"  VerticalAlignment="Center" Width="Auto"/>
                        </Grid>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ViewModeSelectionListBoxStyle" TargetType="ListBox">
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="IsTabStop" Value="True" />
    <Setter Property="ItemContainerStyle" Value="{StaticResource ListBoxItemStyle1}" />
    <Setter Property="Focusable" Value="True" />
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>    

如果我将VisualStateGroup从“ FocusStates”更改为SelectionStates,则其行为相同。 我希望它与焦点而不是选择相关联,因为如果用户单击某处并且另一个控件也将具有相似的边框,则UI中可能存在视觉不匹配。

顺便说一句:在另一个msdn站点上,我读到:“对于在其ControlTemplate中定义的每个VisualStateGroup,该控件始终处于一种状态,并且只有当它从同一VisualStateGroup进入另一种状态时,才保留该状态。” 从我的代码背后,我确保了listBoxItem仍然是重点。 此外,我试图在鼠标离开我的listBoxItem之后强制进入该状态-无结果(简化:ActiveViewDefinition替代了listbox中实际关注的项目):

        private void It_MouseLeave(object sender, MouseEventArgs e)
        {
            ListBoxItem lbItem = sender as System.Windows.Controls.ListBoxItem;
            if (lbItem != null && lbItem.Content == ActiveViewDefinition)
            {
                VisualStateManager.GoToState(lbItem, "Focused", true);
            }
        }

简单。 来自不同组的VisualState操纵相同元素的相同属性。 您始终需要使用单独的元素(或使用共享元素的单独属性)来指示不同组中的状态,否则它们自然会与其他设置发生冲突和混乱(如您所观察到的)。

伪xaml中的示例:

<VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Normal"><NoChange/></VisualState>
    <VisualState x:Name="MouseOver"><Change What="TheBorder" Color="Red"/></VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
    <VisualState x:Name="Focused"><Change What="TheBorder" Color="Blue"/></VisualState>
</VisualStateGroup>

<Border x:Name="TheBorder" Color="Transparent"/>

最初,边框是透明的。 现在,当我们将鼠标移到边框上时会发生什么? mouseOver状态将其更改为红色。 现在,我们单击控件(假设它已被选中并且可以集中显示)。 focusState将其更改为蓝色。 现在我们将鼠标移开。 normalState将其更改为其初始状态:透明。 focusState效果丢失。

让我们看一下修改后的示例:

<VisualStateGroup x:Name="CommonStates">
    <VisualState x:Name="Normal"><NoChange/></VisualState>
    <VisualState x:Name="MouseOver"><Change What="TheMouseoverBorder" Color="Red"/></VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
    <VisualState x:Name="Focused"><Change What="TheFocusBorder" Color="Blue"/></VisualState>
</VisualStateGroup>

<Border x:Name="TheFocusBorder" Color="Transparent"/>
<Border x:Name="TheMouseoverBorder" Color="Transparent"/>

最初,两个边界都是透明的。 现在,当我们将鼠标移到它们上方时会发生什么? mouseOver状态将TheMouseoverBorder更改为红色。 现在,我们单击控件(假设它已被选中并且可以集中显示)。 focusState将TheFocusBorder更改为蓝色。 现在我们将鼠标移开。 normalState将TheMouseoverBorder更改回透明状态。 focusState仍然可见,因为TheFocusBorder不受其他状态更改的影响,并且仍为蓝色。

[编辑]

如果绝对必须从单独的VisualStateGroups修改同一元素的相同属性,则可以使用某种具有结果输出属性的聚合器,也可以使用某种穿透机制。

我可以想到几种从单独的VisualStateGroups修改同一Foreground属性的解决方案。 您可以尝试一下,看看它们是否有效。

跌倒

<VisualState x:Name="MouseOver"><Change What="Outer" ForegroundColor="Red"/></VisualState>
...
<VisualState x:Name="Focused"><Change What="Inner" ForegroundColor="Blue"/></VisualState>

<ContentControl x:Name="Outer">
    <ContentControl x:Name="Inner">
    ...
    </ContentControl>
</ContentControl>

理论上:如果两个状态都处于活动状态,则内部状态将获胜(焦点:蓝色),如果仅鼠标悬停状态处于活动状态,则该属性不会在内部显式设置,而是将从外部继承。 未经测试。 试试吧。

聚合器

<VisualState x:Name="MouseOver"><Change What="Aggregator" MouseOverColor="Red"/></VisualState>
...
<VisualState x:Name="Focused"><Change What="Aggregator" FocusedColor="Blue"/></VisualState>

<InvisibleAggregator x:Name="Aggregator"/>
<ContentControl Foreground="{Binding ElementName=Aggregator, Path=EffectiveColor}"/>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM