2017-07-03 75 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