如何在ScrollViewer和WrapPanel中查找可见元素

时间:2014-09-27 23:37:19

标签: wpf scrollviewer wrappanel

我使用ScrollViewer包围了WrapPanel,我想在点击按钮时在屏幕上找到可见元素。

我的代码如下:

<ScrollViewer>
    <WrapPanel>
        <Label Width="500" Height="500"/>
        <Label Width="500" Height="500"/>
        <Label Width="500" Height="500"/>
        ....
        ....
        ....
        <Label Width="500" Height="500"/>
        <Label Width="500" Height="500"/>
        <Label Width="500" Height="500"/>
    </WrapPanel>
</ScrollPanel>

当ScrollViewer滚动到某个偏移量时,如何找到可见的Label元素。

1 个答案:

答案 0 :(得分:0)

希望这会让你开始(你可能想用'包含'来改变'svViewportBounds.IntersectsWith'。

public partial class MainWindow : Window
{
    public string VisibleItems
    {
        get { return (string)GetValue(VisibleItemsProperty); }
        set { SetValue(VisibleItemsProperty, value); }
    }

    public static readonly DependencyProperty VisibleItemsProperty =
        DependencyProperty.Register("VisibleItems", typeof(string), typeof(MainWindow), new PropertyMetadata("??"));

    public List<string> Items { get; private set; }

    public MainWindow()
    {
        Items = new List<string>();

        for (int i = 0; i < 25; ++i )
        {
            Items.Add("item_" + i);
        }

        DataContext = this;
        InitializeComponent();
    }

    void OnScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        ScrollViewer sv = (ScrollViewer)sender;
        var visibleItems = new List<int>();
        Rect svViewportBounds = new Rect(sv.HorizontalOffset, sv.VerticalOffset, sv.ViewportWidth, sv.ViewportHeight);

        for(int i = 0; i < Items.Count; ++i)
        {
            var container = itemsHost.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
            if(container != null)
            {
                var offset = VisualTreeHelper.GetOffset(container);
                var bounds = new Rect(offset.X, offset.Y, container.ActualWidth, container.ActualHeight);

                if (svViewportBounds.IntersectsWith(bounds))
                {
                    visibleItems.Add(i);
                }
            }
        }

        VisibleItems = string.Join(", ", visibleItems.ToArray());
    }
}

<Window x:Class="WpfApplication59.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow"
    WindowStartupLocation="CenterScreen"
    Width="400"
    Height="400">
<DockPanel>
    <Border BorderThickness="1"
            BorderBrush="Black"
            DockPanel.Dock="Top">
        <TextBlock Text="{Binding VisibleItems}"
                   Margin="5" />
    </Border>

    <ItemsControl ItemsSource="{Binding Items}" Name="itemsHost">
        <ItemsControl.Template>
            <ControlTemplate>
                <ScrollViewer HorizontalScrollBarVisibility="Disabled"
                              ScrollChanged="OnScrollViewerScrollChanged">
                    <WrapPanel IsItemsHost="True" />
                </ScrollViewer>
            </ControlTemplate>
        </ItemsControl.Template>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Border BorderThickness="1"
                        BorderBrush="Black"
                        Width="100"
                        Height="100">
                    <Label Content="{Binding}" />
                </Border>
            </DataTemplate>
        </ItemsControl.ItemTemplate>

        <ItemsControl.ItemContainerStyle>
            <Style TargetType="{x:Type ContentPresenter}">
                <Setter Property="Margin"
                        Value="4" />
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
</DockPanel>