/// <summary>
    /// 间接实现了虚拟化的ListBox
    /// 子项必须实现IVisible接口
    /// 你可以在IsVisible发生改变时实现一系列自定义动作
    /// 比如:当IsVisible = false时,清空子项的内容;当IsVisible = true时,还原子项的内容
    /// </summary>
    public class VirtualizedListBox : ListBox
    {
        private ScrollViewer scrollViewer;

        public override void OnApplyTemplate()
        {
            scrollViewer = FindVisualChild<ScrollViewer>(this);
            if (scrollViewer != null)
            {
                scrollViewer.ScrollChanged -= OnScrollChanged;
                scrollViewer.ScrollChanged += OnScrollChanged;
            }
        }

        #region 事件
        /// <summary>
        /// 滚动条滚动事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            foreach (IVisible item in this.Items)
            {
                var listBoxItem = (FrameworkElement)this.ItemContainerGenerator.ContainerFromItem(item);
                item.IsVisible = IsChildVisibleInParent(listBoxItem, scrollViewer);
            }
        } 
        #endregion

        #region 私有方法
        /// <summary>
        /// 判断子控件是否在父控件中可见
        /// </summary>
        /// <param name="child">子控件</param>
        /// <param name="parent">父控件</param>
        /// <returns></returns>
        private bool IsChildVisibleInParent(FrameworkElement child, FrameworkElement parent)
        {
            var childTransform = child.TransformToAncestor(parent);
            var childRectangle = childTransform.TransformBounds(new Rect(new Point(0, 0), child.RenderSize));
            var ownerRectangle = new Rect(new Point(0, 0), parent.RenderSize);
            return ownerRectangle.IntersectsWith(childRectangle);
        }

        public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
        {
            if (obj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child != null && child is T)
                    {
                        return (T)child;
                    }
                    T childItem = FindVisualChild<T>(child);
                    if (childItem != null) return childItem;
                }
            }
            return null;
        } 
        #endregion
    }
VirtualizedListBox

相关文章:

  • 2021-05-24
  • 2021-08-29
  • 2022-01-18
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-16
  • 2021-06-17
猜你喜欢
  • 2021-12-16
  • 2022-12-23
  • 2022-12-23
  • 2021-12-28
  • 2021-12-13
  • 2021-12-16
相关资源
相似解决方案