LIstView KeyBorad навигации, как Windows Explorer в WPF - PullRequest
1 голос
/ 18 ноября 2011

Я хочу, чтобы навигация с помощью клавиатуры осуществлялась в IconView в Windows Explorer, т. Е. Если мы переместимся в конец ширины экрана, выбор должен перейти к следующей строке ....

    <ListView Name="lv"
              Grid.Row="1"
              Width="Auto"
              Height="Auto"
              IsTextSearchEnabled="True"
              ItemsSource="{Binding Path=Persons}"
              KeyboardNavigation.DirectionalNavigation="Continue"
              SelectedItem="{Binding Path=SelectedPerson}"
              SelectionMode="Single"
              View="{StaticResource ResourceKey=plainView}">
        <ListView.Resources>
            <Style TargetType="{x:Type ListViewItem}" BasedOn="{StaticResource {x:Type ListViewItem}}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
                        <Setter Property="IsEnabled"  Value="False"></Setter>    
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ListView.Resources>
    </ListView>

Вот код для того, что я пытаюсь

Ответы [ 2 ]

0 голосов
/ 18 ноября 2011

Единственный способ добиться этого - вручную интерпретировать нажатую клавишу в PreviewKeyDown событие и установить выбранный индекс. Вы должны установить для handled значение true, иначе представление списка будет также интерпретировать клавиши, что приводит к неправильной навигации по клавишам.

Вот пример с двумя ключами:

    private void listView_PreviewKeyDown(object sender, KeyEventArgs e)
    {
      if (listView.SelectedIndex >= 0)
      {
        if (e.Key == Key.Right)
        {
          listView.SelectedIndex++;
        }
        if (e.Key == Key.Left)
        {
          listView.SelectedIndex--;
        }
      e.Handled = true;
      }
   }

РЕДАКТИРОВАТЬ: 100% чистый MVVM способ с использованием MVVMLight Toolkit

XAML:

    xmlns:mvvmLight="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    >
<Grid>
<ListView SelectedIndex="{Binding SelectedIndex}" ItemsSource="{Binding Items}" x:Name="listView">
  <i:Interaction.Triggers>
    <i:EventTrigger EventName="PreviewKeyDown">
      <mvvmLight:EventToCommand PassEventArgsToCommand="True" Command="{Binding PreviewKeyDownCommand}"></mvvmLight:EventToCommand>
    </i:EventTrigger>
  </i:Interaction.Triggers>

ViewModel:

public ICommand PreviewKeyDownCommand
{
  get
  {
    return new RelayCommand<Object>(x => this.PreviewKeyDown(x as KeyEventArgs));
  }
}

private void PreviewKeyDown(KeyEventArgs e)
{
  if (SelectedIndex >= 0)
  {
    if (e.Key == Key.Right)
    {
      SelectedIndex++;
    }
    if (e.Key == Key.Left)
    {
      SelectedIndex--;
    }
  }
  e.Handled = true;
}

private int _selectedIndex;

public int SelectedIndex
{
  get { return _selectedIndex; }
  set
  {
    _selectedIndex = value;
    NotifyPropertyChanged("SelectedIndex");
  }
}
0 голосов
/ 18 ноября 2011

В вашем Generic.xaml определите стиль по умолчанию для ListView следующим образом:

<Style TargetType="{x:Type ListView}">
        <Setter Property="SnapsToDevicePixels" Value="true" />        
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Visible" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Visible" />
        <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="FontFamily" Value="Trebuchet MS" />
        <Setter Property="FontSize" Value="12" />
        <Setter Property="BorderBrush" Value="{DynamicResource ControlBorderBrush}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="Padding" Value="1" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListView}">
                    <Grid>
                        <Border x:Name="Border"
                                Background="{DynamicResource ControlBackgroundBrush}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                CornerRadius="1">
                            <ScrollViewer Margin="{TemplateBinding Padding}" IsTabStop="False">                                
                                    <ItemsPresenter/>
                            </ScrollViewer>
                        </Border>
                        <Border x:Name="DisabledVisualElement"
                                Background="#A5FFFFFF"
                                BorderBrush="#66FFFFFF"
                                BorderThickness="1"
                                IsHitTestVisible="false"
                                Opacity="0" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter TargetName="DisabledVisualElement" Property="Opacity" Value="1" />
                        </Trigger>
                        <Trigger Property="IsGrouping" Value="true">
                            <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="ItemsPanel">
            <Setter.Value >
                <ItemsPanelTemplate>
                    <WrapPanel Height="{Binding ActualHeight,
                                                            RelativeSource={RelativeSource AncestorType=Border}}"
                                           MinWidth="{Binding (ListView.View).MinWidth,
                                                              RelativeSource={RelativeSource Mode=FindAncestor,
                                                                                             AncestorType={x:Type ListView}}}"
                                           Focusable="False"
                                           IsItemsHost="True"
                               KeyboardNavigation.DirectionalNavigation="Contained"
                                           ItemWidth="{Binding (ListView.View).ItemWidth,
                                                               RelativeSource={RelativeSource Mode=FindAncestor,
                                                                                              AncestorType={x:Type ListView}}}"                                           
                                           Orientation="Vertical" />
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Небольшое объяснение: ваш WrapPanel брал весь доступный размер вашего ScrollViewer, который практически бесконечен. Если вы хотите, чтобы ваши элементы можно было прокручивать в вертикальной панели WrapPanel, вы должны ограничить свой рост в горизонтальной ширине.

...