यदि आप नीचे स्क्रॉल और फिर माउस के साथ ऊपरी दिखाई कंटेनर का चयन एक virtualizing एक के लिए के रूप में एक गैर virtualizing ItemsControl
(ScrollViewer.CanContentScroll="False"
) के लिए एक ही प्रभाव मिल जाएगा। यह कोड में भी किया जा सकता है।
जब CanContentScroll
झूठी पर सेट है, वर्चुअलाइजिंग बंद है इसलिए सभी कंटेनर हर समय उत्पन्न होंगे। शीर्ष दृश्य कंटेनर प्राप्त करने के लिए हम ScrollViewer
के VerticalOffset
तक पहुंचने तक शीर्ष से कंटेनरों को फिर से सक्रिय कर सकते हैं। एक बार जब हम इसे प्राप्त कर लेंगे तो हम इसे BringIntoView
पर कॉल कर सकते हैं और यह शीर्ष पर अच्छी तरह से संरेखित होगा जैसे वर्चुअलाइजेशन का उपयोग किया जा रहा था।
उदाहरण
<ListBox ItemsSource="{Binding MyCollection}"
ScrollViewer.CanContentScroll="False"
ScrollViewer.ScrollChanged="listBox_ScrollChanged" >
ईवेंट हैंडलर में शीर्ष दिखाई कंटेनर पर कॉल BringIntoView
private void listBox_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
ItemsControl itemsControl = sender as ItemsControl;
ScrollViewer scrollViewer = e.OriginalSource as ScrollViewer;
FrameworkElement lastElement = null;
foreach (object obj in itemsControl.Items)
{
FrameworkElement element = itemsControl.ItemContainerGenerator.ContainerFromItem(obj) as FrameworkElement;
double offset = element.TransformToAncestor(scrollViewer).Transform(new Point(0, 0)).Y + scrollViewer.VerticalOffset;
if (offset > e.VerticalOffset)
{
if (lastElement != null)
lastElement.BringIntoView();
break;
}
lastElement = element;
}
}
करने के लिए केवल इस प्रभाव को प्राप्त जब आप PageDown
कॉल करना चाहते हैं में, उदाहरण के लिए एक बटन क्लिक करें, आप मुझे एक एक्सटेंशन बना सकते हैं ListBox
के लिए थोड LogicalPageDown
कहा जाता है।
listBox.LogicalPageDown();
ListBoxExtensions
public static class ListBoxExtensions
{
public static void LogicalPageDown(this ListBox listBox)
{
ScrollViewer scrollViewer = VisualTreeHelpers.GetVisualChild<ScrollViewer>(listBox);
ScrollChangedEventHandler scrollChangedHandler = null;
scrollChangedHandler = (object sender2, ScrollChangedEventArgs e2) =>
{
scrollViewer.ScrollChanged -= scrollChangedHandler;
FrameworkElement lastElement = null;
foreach (object obj in listBox.Items)
{
FrameworkElement element = listBox.ItemContainerGenerator.ContainerFromItem(obj) as FrameworkElement;
double offset = element.TransformToAncestor(scrollViewer).Transform(new Point(0, 0)).Y + scrollViewer.VerticalOffset;
if (offset > scrollViewer.VerticalOffset)
{
if (lastElement != null)
lastElement.BringIntoView();
break;
}
lastElement = element;
}
};
scrollViewer.ScrollChanged += scrollChangedHandler;
scrollViewer.PageDown();
}
}
मैं अपने प्रश्न है कि आप पहले से ही ScrollViewer
मिला में देखा है, लेकिन मैं GetVisualChild
के एक कार्यान्वयन जोड़ रहा किसी और को इस सवाल का
public static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
स्रोत
2011-09-06 11:55:11
@Zmaster: भूल गए कि 'मार्जिन' इत्यादि कंटेनर की सापेक्ष स्थिति ढूंढते समय शामिल हो सकते हैं। –
के अनुसार मेरा उत्तर अपडेट किया गया अंत में मैंने लक्ष्य ऑफसेट की गणना करके स्क्रॉलटॉऑफसेट() का उपयोग करने का निर्णय लिया कि प्रत्येक आइटम की ऊंचाई समान है (यह मेरा मामला है)। यह वस्तुओं को फिर से शुरू करने से अधिक कुशल है। दूसरी तरफ आपका समाधान विभिन्न वस्तुओं की ऊंचाई पर भी काम करता है, इसलिए मैंने इसे उत्तर के रूप में स्वीकार कर लिया। – Zmaster