2017-07-03 71 views
0

我有一个虚拟ItemsControl与标签或文本框的列表。由于数据量大,需要虚拟化。现在我想通过与键盘的聆听选项卡。这很好,直到它到达可见列表的末尾。比焦点离开列表。有没有办法“滚动”下一个可调焦控件的列表?问题是不是列表中的每个项目都有一个可调焦的控件。通过虚拟化ItemControl /列表挂钩

下面是一个例子:

Here is an example:

有没有什么有效的解决方案?例如,加载10个可见的项目。或者找到上次加载的可调焦项目并按代码滚动。或者在显示列表后在背景中显示所有数据。内存不是瓶颈,它是列表的渲染时间。

我按照这些Virtualizing an ItemsControl?

这里是行不通例如

<ItemsControl DockPanel.Dock="Top" x:Name="lb" Height="200" ItemsSource="{Binding testList}" 
      KeyboardNavigation.TabNavigation="Cycle" 
      VirtualizingStackPanel.IsVirtualizing="True" 
      VirtualizingStackPanel.VirtualizationMode="Standard" 
       ScrollViewer.CanContentScroll="True" 
        AlternationCount="4" 
      > 

     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <VirtualizingStackPanel IsItemsHost="True" Orientation="Vertical" x:Name="virtualizingStackPanel" /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <StackPanel> 
        <TextBox Text="{Binding Path=., Mode=OneWay}" Name="txtTest"> 
         <TextBox.Style> 
          <Style TargetType="TextBox"> 
           <Setter Property="Visibility" Value="Collapsed" /> 
          </Style> 
         </TextBox.Style> 
        </TextBox> 
        <Label >space</Label> 
       </StackPanel> 
       <DataTemplate.Triggers> 
        <Trigger Property="ItemsControl.AlternationIndex" Value="0"> 
         <Setter Property="Visibility" Value="visible" TargetName="txtTest"/> 
        </Trigger> 
       </DataTemplate.Triggers> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
     <ItemsControl.Template> 
      <ControlTemplate> 
       <Border 
     BorderThickness="{TemplateBinding Border.BorderThickness}" 
     Padding="{TemplateBinding Control.Padding}" 
     BorderBrush="{TemplateBinding Border.BorderBrush}" 
     Background="{TemplateBinding Panel.Background}" 
     SnapsToDevicePixels="True"> 
        <ScrollViewer 
       Padding="{TemplateBinding Control.Padding}" 
       Focusable="False" > 
         <ItemsPresenter 
        SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Name="presenter"/> 
        </ScrollViewer> 
       </Border> 
      </ControlTemplate> 
     </ItemsControl.Template> 
    </ItemsControl> 

代码隐藏

public List<string> testList { 

     get 
     { 

      List< string> a = new List<string>(); 
      for (int i = 0; i < 10000; i++) 
      { 
       a.Add(i.ToString()); 
      } 
      return a; 
     } 


    } 

回答

1

设置KeyboardNavigation.TabNavigation属性Cycle和容器来falseIsTabStop财产。这个工作对我来说:

<ListBox x:Name="lb" Height="400" KeyboardNavigation.TabNavigation="Cycle"> 
    <ListBox.ItemContainerStyle> 
     <Style TargetType="ListBoxItem"> 
      <Setter Property="IsTabStop" Value="False"/> 
     </Style> 
    </ListBox.ItemContainerStyle> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <TextBox Text="{Binding Path=., Mode=OneWay}" /> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

WPF:如何选项卡项目之间的一个列表框中:https://social.technet.microsoft.com/wiki/contents/articles/25152.wpf-how-to-tab-between-items-in-a-listbox.aspx

你的榜样工程。但在我的项目中没有evey项目有一个可以控制的焦点。

然后你将不得不写一些代码。例如,您可以处理PreviewKeyDown事件容器:

<ItemsControl.ItemContainerStyle> 
    <Style TargetType="ContentPresenter"> 
     <EventSetter Event="PreviewKeyDown" Handler="lb_PreviewKeyDown" /> 
    </Style> 
</ItemsControl.ItemContainerStyle> 

下面是一些示例代码,应该给你的想法:

private void lb_PreviewKeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Key == Key.Tab) 
    { 
     Dispatcher.BeginInvoke(new Action(() => 
     { 
      ContentPresenter cp = sender as ContentPresenter; 
      VirtualizingStackPanel sp = FindParent<VirtualizingStackPanel>(cp); 
      if (sp != null) 
      { 
       int uiIndex = sp.Children.IndexOf(cp); 
       if (uiIndex > -1) 
       { 
        ContentPresenter cpp; 
        while (++uiIndex < sp.Children.Count - 1) 
        { 
         cpp = sp.Children[uiIndex] as ContentPresenter; 
         if (cpp != null) 
         { 
          TextBox textBox = FindChild<TextBox>(cpp); 
          if (textBox != null && textBox.Visibility == Visibility.Visible) 
           return; 
         } 
        } 

        //no TextBox was found. generate the containers programmatically 
        int sourceIndex = lb.Items.IndexOf(cp.DataContext); 
        if (sourceIndex > -1) 
        { 
         ScrollViewer sv = FindChild<ScrollViewer>(lb); 
         if (sv != null) 
         { 
          while (++sourceIndex < lb.Items.Count - 1) 
          { 
           cpp = lb.ItemContainerGenerator.ContainerFromIndex(sourceIndex) as ContentPresenter; 
           while (cpp == null) 
           { 
            sv.ScrollToVerticalOffset(sv.VerticalOffset + 1); 
            lb.UpdateLayout(); 
            cpp = lb.ItemContainerGenerator.ContainerFromIndex(sourceIndex) as ContentPresenter; 
           } 

           TextBox textBox = FindChild<TextBox>(cpp); 
           if (textBox != null && textBox.Visibility == Visibility.Visible) 
           { 
            textBox.Focus(); 
            return; 
           } 
          } 
         } 
        } 
       } 
      } 
     }), System.Windows.Threading.DispatcherPriority.Background); 
    } 
} 

private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject 
{ 
    var parent = VisualTreeHelper.GetParent(dependencyObject); 

    if (parent == null) return null; 

    var parentT = parent as T; 
    return parentT ?? FindParent<T>(parent); 
} 

private static T FindChild<T>(DependencyObject dependencyObject) where T : DependencyObject 
{ 
    if (dependencyObject == null) return null; 

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++) 
    { 
     var child = VisualTreeHelper.GetChild(dependencyObject, i); 

     var result = (child as T) ?? FindChild<T>(child); 
     if (result != null) return result; 
    } 
    return null; 
} 
+0

与KeyboardNavigation.TabNavigation =“周期”的重点转到“可见”列表中的第一个元素,但不包含真实列表中的下一个元素 – Alex

+0

适用于我的示例。你甚至尝试过吗?你也应该阅读:https://stackoverflow.com/help/how-to-ask – mm8

+0

是的,我试过这些。你的例子工作。但在我的项目中没有evey项目有一个可以控制的焦点。在我的帖子中看到我的不工作示例 – Alex