2012-03-02 2 views
0

У меня есть кнопка над списком, в которой есть элементы в горизонтальном расположении. Если у моей кнопки есть фокус, и я нажимаю клавишу «вниз» на клавиатуре, тогда в списке появляется фокус. Если я затем нажимаю клавишу, то в списке все еще есть фокус. Можно ли изменить это поведение, поэтому, когда я нажимаю клавишу, моя кнопка снова фокусируется?Перемещение из списка в WPF

EDIT: Я должен добавить, что использую 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

Не знаю, существует ли прямое решение MVVM с прямой передачей этой проблемы. Причина в том, что ListBox фактически использует события «вверх» и «вниз» для навигации по элементам списка (что является желаемым эффектом в большинстве случаев), тогда как кнопки позволят событиям перейти в класс FocusManager.

Однако, как и во всем, есть способы обхода пути, вот как я это сделаю: Прежде всего вам нужно перехватить событие Key-Down и искать направленные входы (вверх-вниз-влево-вправо) , Я бы подумал, что вам все равно придется перемещаться по клавишам в вашем списке, поэтому в обработчике событий я обязательно проверю, есть ли у меня первый (или последний) элемент, а затем с помощью метода MoveFocus() с TraversalRequest - FocusNavigationDirection.Up/Down/Next/Previous для перемещения фокуса.

Чтобы убедиться, что ваш код-код чист, создайте новый элемент управления ListBox и разместите там свое событие. Фактически, в производном контроле не используйте событие, переопределите метод OnKeyDown. Таким образом, вы пишете логику фокуса в своем пользовательском элементе управления, а не в представлении.

Код:

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); 
    } 
+0

Спасибо Алекс, я использовал комбинацию KeyboardNavigation.DirectionalNavigation = «Продолжить» для любого горизонтального ListBoxes, который занимал всю ширину приложения (Это сделано вверх и вниз работы), а также с вашим решением для любых списков, которые занимают лишь небольшой процент от ширины или высоты приложения. – Oli

Смежные вопросы