0

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

4

2 回答 2

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

于 2012-11-29T04:40:25.767 回答
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;
}
于 2012-11-29T04:54:35.590 回答