ItemsControl项目,不在视图中

时间:2013-10-17 08:36:50

标签: wpf wpf-controls itemscontrol

我有一个ScrollViewer,其中有一个ItemsControlItemsControl绑定到ObservableCollectionItemsControl有一个ItemTemplate,我在其中提供TextBox来显示数据。

数据正确显示。我已为每个TextBox添加了一个弹出窗口,以显示其中展示位置为Top的其他数据。

我面临的问题是当我滚动一个项目不在视图中时,我需要隐藏弹出窗口并在项目出现时再次显示它。

我已订阅了scrollviewer的ScrollChanged事件,但如何获取超出范围隐藏弹出窗口的项目TextBox

感谢

2 个答案:

答案 0 :(得分:3)

您可以使用Lester WPF \ SL博客上的Determining the Visibility of Elements inside ScrollViewer文章中的方法来确定特定项目是否在ScrollViewer中可见。来自那篇博客:

// position of your visual inside the scrollviewer    
GeneralTransform childTransform = ContainedObject.TransformToAncestor(ScrollViewerObj);
Rect rectangle = childTransform.TransformBounds(new Rect(new Point(0,0), 
    ContainedObject.RenderSize));

// Check if the elements Rect intersects with that of the scrollviewer's
Rect result = Rect.Intersect(new Rect(new Point(0, 0), ScrollViewerObj.RenderSize), 
    rectangle);

// if result is Empty then the element is not in view
if (result == Rect.Empty)
{
    ContainedObject.IsPopupOpen = false; // <<< Close relevant popup here
}
else
{
    //obj is partially Or completely visible
    //skip or bring obj in view.
}

显然,要使其正常工作,您需要向绑定到bool IsPopupOpen属性的数据的数据对象添加新的TextBox.Text属性。然后,您还需要Bind这个Popup.IsOpen属性:

<Popup IsOpen="{Binding IsPopupOpen}" StaysOpen="False" ... />

更新&gt;&gt;&gt;

滚动ScrollViewer.ScrollChanged时,ScrollViewer事件会经常被调用。直接在该事件处理程序中执行任何代码确实是不明智的,但ScrollChangedEventArgs对象具有一些可以帮助我们的属性。有关这些属性的详细信息,请查看MSDN上的ScrollChangedEventArgs Class页面。

您可以在名为VerticalChangeHorizontalChange的事件处理程序中访问两个属性,这些属性应显示自上次事件以来ScrollViewer已滚动多少。 [现在已经有一段时间了,所以我不能保证它们是正确的属性,但是如果你在事件处理程序中使用MSDN上ScrollChangedEventArgs.VerticalChange Property页面的示例代码,那么读出应该给你一个线索关于哪些是正确使用的属性。]

因此,找到相关属性后,您可以在处理程序中使用它们来确定是否执行代码...尝试这样的事情:

double totalVerticalChange = 0.0;
double minimumValue = 24.0; // set this to whatever you want as a minimum scroll value
...
private void ScrollViewer_Changed(object sender, ScrollChangedEventArgs e)
{
    if (totalVerticalChange + e.VerticalChange >= minimumValue)
    {
        totalVerticalChange = 0.0;
        // perform your functionality here
    }
    else totalVerticalChange += e.VerticalChange;
}

如果此处有错误,请原谅我,因为我目前无法在Visual Studio中查看此内容,但希望您明白这一点......基本上,就像我们'过滤'了一些事件一样。< / p>

答案 1 :(得分:2)

查看this question here,其中讨论了确定ScrollViewer中对象的可见度。

基本辅助方法:

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);
    return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}

以及执行您想要执行的操作的示例函数:

private void Scroll_Changed(object sender, ScrollChangedEventArgs e)
{
    Object o = sender;
    bool elementIsVisible = false;

    foreach (FrameworkElement child in this.stackPanel1.Children)
    {
        if (child != null)
        {
            elementIsVisible = this.IsUserVisible(child, this.scroller);

            if (!elementIsVisible)
            {
                // Logic to disable popups here...
            }
        }
    }
}