2012-03-02 91 views
0

我有一個按鈕上方的列表框中有它的項目在水平的allignment。如果我的按鈕有焦點,並且我按下鍵盤上的向下鍵,那麼列表框會變得焦點。如果我然後按下鍵,那麼列表框仍然有焦點。這種行爲可以改變,所以當我按下鍵時,我的按鈕又有焦點了嗎?導航列表框在WPF

編輯:我應該添加我使用MVVM,所以想保持解決方案的代碼隱藏,如果possable。

下面是我的列表框的完整代碼。

<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類。

然而,至於所有的東西,有一些解決方法,所以我想這樣做: 首先,您需要攔截按鍵事件並查找方向輸入(上下左右) 。我認爲你仍然想用列表中的鍵進行導航,所以在事件處理程序中,我會確保測試我是否在第一個(或最後一個)元素上,然後在TraversalRequest中使用MoveFocus()方法 - 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的組合=「繼續」任何水平列表框是拿起了應用程序的整個寬度(這使上下工作)沿與您的解決方案的任何列表框只佔用了一小部分的應用程序的寬度或高度。 – Oli 2012-03-08 21:01:35