我在列表框上方有一个按钮,其中的项目处于水平对齐状态。如果我的按钮有焦点,我按下键盘上的向下键,然后列表框获得焦点。如果我然后按键,则列表框仍然具有焦点。可以改变这种行为,所以当我按下键时我的按钮再次聚焦了吗?
编辑:我应该添加我正在使用MVVM,所以如果可能的话,希望保持解决方案不受代码隐藏。
以下是我的列表框的完整代码。
<ListBox Grid.Row="2" ItemsSource="{Binding Movies}" TextSearch.TextPath="Title" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Template>
<ControlTemplate>
<Grid>
<ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="poster">
<Image x:Name="posterImage" RenderOptions.BitmapScalingMode="LowQuality" Source="{Binding Poster}" Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}">
</Image>
<TextBlock Text="{Binding PosterOverlayText}" Style="{DynamicResource PosterOverlayText}" Width="{Binding ActualWidth, ElementName=posterImage}"/>
<Grid.LayoutTransform>
<TransformGroup>
<ScaleTransform x:Name="st" ScaleX="0.85" ScaleY="{Binding ScaleX, RelativeSource={RelativeSource Self}}"/>
</TransformGroup>
</Grid.LayoutTransform>
<Grid.InputBindings>
<MouseBinding Command="{x:Static Commands:MediaFiles.PlaySelectedMovie}" Gesture="LeftDoubleClick" />
</Grid.InputBindings>
</Grid>
<DataTemplate.Resources>
<CubicEase x:Key="ease" EasingMode="EaseOut"/>
</DataTemplate.Resources>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.3"
EasingFunction="{StaticResource ease}"
Storyboard.TargetName="st"
Storyboard.TargetProperty="ScaleX"
To="1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.3"
EasingFunction="{StaticResource ease}"
Storyboard.TargetName="st"
Storyboard.TargetProperty="ScaleX"
To="0.85"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.InputBindings>
<KeyBinding Command="{x:Static Commands:MediaFiles.PlaySelectedMovie}" Gesture="ENTER"/>
</ListBox.InputBindings>
</ListBox>
答案 0 :(得分:0)
不知道是否有一个直接的MVVM接受解决此问题的方法。原因是ListBox实际上使用键向上和按键事件来浏览列表项(大多数时候这是期望的效果),而按钮将让事件进入FocusManager类。
然而,至于那里的一切,有解决方法,所以这里是我将如何做到这一点: 首先,您需要拦截Key-Down事件并寻找方向输入(上下左右)。我认为您仍然希望使用列表中的键进行导航,因此,在事件处理程序中,我将确保测试我是否在第一个(或最后一个)元素上,然后使用TraversalRequest的MoveFocus()方法 - FocusNavigationDirection.Up / Down / Next / Previous移动焦点。
最后,为了确保您的代码隐藏是干净的,请创建一个新的ListBox派生控件并在那里举行您的活动。实际上,在派生控件中,不要使用事件,覆盖OnKeyDown方法。这样,您就可以在自定义控件中编写焦点逻辑,而不是View。
代码:
protected override void OnKeyDown(KeyEventArgs e)
{
if ((e.Key == Key.Up ||e.Key == Key.Left) && SelectedIndex == 0)
{
//.Previous will navigate correctly to the last element
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Previous));
return;
}
if (e.Key == Key.Down && this.SelectedIndex == this.Items.Count - 1)
{
//.Next will navigate to the first item in the list rather than skip to the next control. We will use Down or Right.
//this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Down));
return;
}
if (e.Key == Key.Right && this.SelectedIndex == this.Items.Count - 1)
{
this.MoveFocus(new TraversalRequest(FocusNavigationDirection.Right));
return;
}
base.OnKeyUp(e);
}