/// <summary> ///The virtualized ListBox is implemented indirectly///children must implement the Ivisible interface///you can implement a series of custom actions when the IsVisible changes///For example: when isvisible = False, the contents of the empty subkey; when isvisible = True, the contents of the atomic item are also/// </summary> Public classVirtualizedlistbox:listbox {PrivateScrollViewer ScrollViewer; Public Override voidOnApplyTemplate () {ScrollViewer= Findvisualchild<scrollviewer> ( This); if(ScrollViewer! =NULL) {scrollviewer.scrollchanged-=onscrollchanged; Scrollviewer.scrollchanged+=onscrollchanged; } } #regionEvent/// <summary> ///scroll bar scrolling Events/// </summary> /// <param name= "Sender" ></param> /// <param name= "E" ></param> Private voidOnscrollchanged (Objectsender, Scrollchangedeventargs e) { foreach(Ivisible Iteminch This. Items) {varListBoxItem = (FrameworkElement) This. Itemcontainergenerator.containerfromitem (item); Item. IsVisible=ischildvisibleinparent (ListBoxItem, scrollViewer); } } #endregion #regionPrivate methods/// <summary> ///determines whether child controls are visible in the parent control/// </summary> /// <param name= "Child" >child controls</param> /// <param name= "parent" >Parent Control</param> /// <returns></returns> Private BOOLischildvisibleinparent (FrameworkElement child, FrameworkElement parent) {varChildtransform =Child . Transformtoancestor (parent); varChildrectangle = Childtransform.transformbounds (NewRect (NewPoint (0,0), child. Rendersize)); varOwnerrectangle =NewRect (NewPoint (0,0), parent. Rendersize); returnOwnerrectangle.intersectswith (Childrectangle); } Public StaticT findvisualchild<t> (DependencyObject obj)whereT:dependencyobject {if(obj! =NULL) { for(inti =0; I < Visualtreehelper.getchildrencount (obj); i++) {DependencyObject child=visualtreehelper.getchild (obj, i); if(Child! =NULL&& Child isT) {return(T) child; } T ChildItem= findvisualchild<t>(child); if(ChildItem! =NULL)returnChildItem; } } return NULL; } #endregion }
Virtualizedlistbox
/// <summary> ///represents a visible type/// </summary> Public Interfaceivisible {/// <summary> ///is visible/// </summary> BOOLIsVisible {Get; Set; } }
ivisible
The core code is the Ischildvisibleinparent method, which determines whether a child control is visible in the parent control.
For a ListBox, you need to determine whether a listboxitem is visible in the ScrollView of the listbox. Then, depending on whether the child is visible or not, the sub-items are processed for indirect virtualization.
Therefore, you need to get the ScrollViewer in the template for the listbox. Thus, the sacrifice of the artifact:
Public StaticT findvisualchild<t> (DependencyObject obj)whereT:dependencyobject {if(obj! =NULL) { for(inti =0; I < Visualtreehelper.getchildrencount (obj); i++) {DependencyObject child=visualtreehelper.getchild (obj, i); if(Child! =NULL&& Child isT) {return(T) child; } T ChildItem= findvisualchild<t>(child); if(ChildItem! =NULL)returnChildItem; } } return NULL; }
Findvisualchild
This method, I think understanding of WPF should all know. I saw this approach even on the first day of learning WPF.
At first, I called this method in the constructor of Virtualizedlistbox, and found that the ScrollViewer obtained was empty.
I think it should be this time that the listbox has not started loading.
I then called this method in the loaded event of the listbox and found that the ScrollViewer was still empty.
What the heck? Feel a bit subversive of the three views.
At last, I was discouraged and smashed the keyboard. In the process of hitting the keyboard, the code becomes.
Hey, don't know if you know. In what case, the listbox is still unable to get to ScrollViewer in the ListBox control template even though it is already loaded (Loaded)?
WPF: A listbox that indirectly supports virtualization