0

次のような ListBoxItem のスタイルがあり、listBoxItem が前述の VisualState のままである場合に「フォーカス」視覚効果が失われるという問題があります。「フォーカスされた」ListBoxItemに適切な視覚効果を強制的に表示するにはどうすればよいですか?

バグを達成するシナリオ:

1) ListBoxItem をクリックします -> フォーカスとスタイルを受け取ります (ok)。

2) ポインターをこの ListBoxItem の上に移動します -> まだフォーカスがあり、「MouseOver」のスタイルを受け取ります (ここで提案されているように、別の VisualStateGroup 'CommonStates' 内にあります: https://msdn.microsoft.com/en-us/library /system.windows.controls.listboxitem%28v=vs.95%29.aspx )(わかりました).

3) マウスを ListBoxItem の境界から離す -> MouseOver(ok) のスタイルを失います。

4) 現在、ListBoxItem は「CommonStates」の「Normal」状態であり、「Focused」でもありますが、「Focused」のスタイリッシュさがありません (これは私の問題です)。

5) この ListBoxItem をクリックしようとしても効果がない

どう対処すればよいか、アドバイスをいただけないでしょうか。

Silverlight を使用しているため、トリガーは禁止されています。

これが私のスタイルです:

    <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に対して常に1つの状態にあり、同じVisualStateGroupから別の状態になったときにのみ状態を離れます。」コード ビハインドから、listBoxItem がまだフォーカスされていることを確認しました。その上、マウスが listBoxItem を離れた後、その状態に強制しようとしていましたが、結果はありませんでした (簡略化: ActiveViewDefinition は、リストボックス内の実際にフォーカスされた項目の代わりです):

        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);
            }
        }
4

1 に答える 1

0

簡単。異なるグループの VisualStates は、同じ要素の同じプロパティを操作します。異なるグループの状態を示すには、常に個別の要素を持つ (または共有要素の個別のプロパティを使用する) 必要があります。

疑似 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"/>

最初は境界線は透明です。Border の上にマウスを移動するとどうなるでしょうか。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 を透明に戻します。TheFocusBorder は他の状態変化の影響を受けず、まだ青色であるため、focusState は引き続き表示されます。

[編集]

別の VisualStateGroup から同じ要素の同じプロパティを絶対に変更する必要がある場合は、結果の出力プロパティを持つある種のアグリゲーターを使用するか、何らかのフォールスルー メカニズムを使用できます。

別の VisualStateGroup から同じ 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}"/>
于 2016-05-30T16:39:25.477 に答える