如何知道列表框视图顶部的项目?

时间:2012-11-29 03:10:18

标签: wpf wpf-controls

我在WPF中使用ListBox控件来显示内容,并且此ListBox中的每个项目具有相同的高度,当我拖动滚动条时,如何知道当前ListBox视图顶部的哪个项目?谢谢。

2 个答案:

答案 0 :(得分:1)

    <Grid DataContext="{Binding ElementName=This}">
    <StackPanel>
        <ListBox Height="100" ScrollViewer.ScrollChanged="ListBox_ScrollChanged">
            <ListBoxItem>1</ListBoxItem>
            <ListBoxItem>2</ListBoxItem>
            <ListBoxItem>3</ListBoxItem>
            <ListBoxItem>4</ListBoxItem>
            <ListBoxItem>5</ListBoxItem>
            <ListBoxItem>6</ListBoxItem>
            <ListBoxItem>7</ListBoxItem>
            <ListBoxItem>8</ListBoxItem>
            <ListBoxItem>9</ListBoxItem>
            <ListBoxItem>10</ListBoxItem>
            <ListBoxItem>11</ListBoxItem>
            <ListBoxItem>12</ListBoxItem>
            <ListBoxItem>13</ListBoxItem>
            <ListBoxItem>14</ListBoxItem>
            <ListBoxItem>15</ListBoxItem>
            <ListBoxItem>16</ListBoxItem>
            <ListBoxItem>17</ListBoxItem>
            <ListBoxItem>18</ListBoxItem>
        </ListBox>
        <TextBlock Text="{Binding TopMostItem}"/>            
    </StackPanel>        
</Grid>

    public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private String _topMost;

    public String TopMostItem
    {
        get { return _topMost; }
        set { _topMost = value; RaisePropertyChanged("TopMostItem"); }
    }

    private void ListBox_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        var lb = sender as ListBox;
        foreach (var lbi in lb.Items)
        {
            var container = lb.ItemContainerGenerator.ContainerFromItem(lbi) as ListBoxItem;
            if (container != null && IsUserVisible(container, lb))
            {
                TopMostItem = container.Content as String;
                return;
            }
        }
    }

    private bool IsUserVisible(FrameworkElement element, FrameworkElement container)
    {
        if (!element.IsVisible)
            return false;
        Rect bounds = element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
        Rect rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
        Rect fudgybounds = new Rect(new Point(bounds.TopLeft.X, bounds.TopLeft.Y), new Point(bounds.BottomRight.X, bounds.BottomRight.Y - 5));
        return rect.Contains(fudgybounds.TopLeft) || rect.Contains(fudgybounds.BottomRight);
    } 

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(name));
    }

    #endregion

IsUserVisible方法礼貌: Find WPF Controls in Viewport

答案 1 :(得分:0)

您可以使用此代码:

public static FrameworkElement GetFirstItem(ListBox listBox)
{
   if (listBox.Items.Count == 0)
      return null;
   VirtualizingStackPanel vsp = VisualTreeHelper.GetParent(listBox.Items[0] as FrameworkElement) as VirtualizingStackPanel;
   if (vsp != null)
   {
      int fvi = (int)vsp.VerticalOffset;
      int vic = (int)vsp.ViewportHeight;
      int index=-1;
      foreach (FrameworkElement item in listBox.Items)
      {
         index++;
         if (index >= fvi && index <= fvi + vic)
           {
              return item;
           }
      }
   }
   return null;
}