2012-08-25 20 views
7

का एक तत्व के लिए मैं एक ItemsControl जो एक ScrollViewer में अपनी वस्तुओं को प्रदर्शित करता है, और वर्चुअलाइजेशन करता है। मैं उस ScrollViewer को उस (ऑफस्क्रीन, इसलिए वर्चुअलाइज्ड) आइटम में स्क्रॉल करने का प्रयास कर रहा हूं जिसमें यह शामिल है। हालांकि, चूंकि आइटम वर्चुअलाइज्ड है, यह वास्तव में स्क्रीन पर मौजूद नहीं है और इसमें कोई स्थिति नहीं है (IIUC)।स्क्रॉल एक virtualising ItemsControl

मैं BringIntoView चाइल्ड तत्व पर की कोशिश की है, लेकिन यह दृश्य में स्क्रॉल नहीं करता है। मैं भी मैन्युअल TransformToAncestor, TransformBounds और ScrollToVerticalOffset, लेकिन TransformToAncestor कभी नहीं देता है के साथ यह कर की कोशिश की है (मैं वर्चुअलाइजेशन की वजह से भी लगता है, क्योंकि यह कोई स्थिति नहीं है, लेकिन मुझे लगता है कि का कोई सबूत नहीं है) के बाद यह कभी नहीं निष्पादित करता है और कोड।

यह एक virtualising ItemsControl साथ एक आइटम के लिए स्क्रॉल करना संभव है? यदि हां, तो कैसे?

उत्तर

9

.NET स्रोत कोड में चारों ओर पोकिंग करने से मुझे ListBox और इसकी ScrollIntoView विधि का उपयोग करने की सलाह मिलती है। इस विधि के कार्यान्वयन जो कि सूचकांक और इसे करने के लिए स्क्रॉल पर आइटम के निर्माण के लिए मजबूर करता VirtualizingPanel.BringIndexIntoView जैसे कुछ internal तरीकों पर निर्भर करता है। तथ्य यह है कि उन लोगों के तंत्र के कई आंतरिक हैं मतलब है कि अगर आप अपने खुद के पर ऐसा करने की कोशिश आप करने वाले हैं एक बुरा समय है।

(चयन इस इसके साथ लाता है बनाने के लिए अदृश्य आप retemplate कर सकते हैं ListBoxItems)

+0

मैं ऐसा करने से बचना चाहता हूं क्योंकि मुझे 'सूची बॉक्स' की "आइटम का चयन करें" क्षमता की आवश्यकता नहीं है।कोई विचार क्यों 'ItemControl' में' ScrollIntoView' नहीं है? –

+0

@ सेठ: जैसा कि मैंने कहा था, आप चयन छुपा सकते हैं, जो परवाह करता है अगर यह परवाह करता है? इसमें स्क्रॉलिंग नहीं है क्योंकि इसे इस तरह से डिजाइन किया गया था, 'आइटम नियंत्रण' आइटम नियंत्रणों का सबसे बुनियादी है, ऐसे बेस क्लास के लिए स्क्रॉलिंग कार्यक्षमता की आवश्यकता नहीं है। –

+0

अब यह पता लगाने के लिए कि 'ListBox' को किसी आइटम को पूरी तरह से देखने पर कैसे स्क्रॉल करना है ... –

11

मैं अब थोड़ी देर के लिए एक आइटम के लिए स्क्रॉल करने के लिए एक VirtualizingStackPanel के साथ एक ItemsControl हो रही पर देख रहा है, और खोजने रखा "एक सूची बॉक्स का प्रयोग करें" उत्तर। मैं नहीं चाहता था, इसलिए मुझे ऐसा करने का एक तरीका मिला। सबसे पहले आपको अपने आइटम्स कंट्रोल के लिए एक नियंत्रण टेम्पलेट सेट अप करने की आवश्यकता है जिसमें उसमें स्क्रोलव्यूयर है (जो कि आपके पास पहले से ही है यदि आप आइटम नियंत्रण का उपयोग कर रहे हैं)। मेरे बुनियादी टेम्पलेट निम्नलिखित (ItemsControl के लिए एक आसान शैली में निहित)

<Style x:Key="TheItemsControlStyle" TargetType="{x:Type ItemsControl}"> 
    <Setter Property="Template"> 
    <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ItemsControl}"> 
       <Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" SnapsToDevicePixels="True"> 
        <ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False" HorizontalScrollBarVisibility="Auto"> 
         <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" /> 
        </ScrollViewer> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

तो मैं मूल रूप से एक पुस्तक दर्शक मेरी सामग्री शामिल करने के जा रहा thats के साथ एक सीमा मिल गया है की तरह लग रहा है। मज़े की बात अब

<ItemsControl x:Name="myItemsControl" [..snip..] Style="{DynamicResource TheItemsControlStyle}" ScrollViewer.CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True"> 

ठीक है:
मेरे ItemsControl साथ परिभाषित किया गया है।

public static void VirtualizedScrollIntoView(this ItemsControl control, object item) { 
     try { 
      // this is basically getting a reference to the ScrollViewer defined in the ItemsControl's style (identified above). 
      // you *could* enumerate over the ItemsControl's children until you hit a scroll viewer, but this is quick and 
      // dirty! 
      // First 0 in the GetChild returns the Border from the ControlTemplate, and the second 0 gets the ScrollViewer from 
      // the Border. 
      ScrollViewer sv = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild((DependencyObject)control, 0), 0) as ScrollViewer; 
      // now get the index of the item your passing in 
      int index = control.Items.IndexOf(item); 
      if(index != -1) { 
       // since the scroll viewer is using content scrolling not pixel based scrolling we just tell it to scroll to the index of the item 
       // and viola! we scroll there! 
       sv.ScrollToVerticalOffset(index); 
      } 
     } catch(Exception ex) { 
      Debug.WriteLine("What the..." + ex.Message); 
     } 
    } 

तो जगह में विस्तार विधि के साथ आप यह सिर्फ ListBox साथी विधि की तरह का प्रयोग करेंगे::

myItemsControl.VirtualizedScrollIntoView(someItemInTheList); 
मैं दिए गए आइटम के लिए स्क्रॉल करने के लिए इसे पाने के लिए किसी भी ItemsControl को संलग्न करने के लिए एक विस्तार विधि बना लिया है

बढ़िया काम करता है!

ध्यान दें कि आप अपने आइटमों को प्राप्त करने के लिए sv.ScrollToEnd() और अन्य सामान्य स्क्रॉलिंग विधियों को भी कॉल कर सकते हैं।

+0

दुर्भाग्य से मैं पिक्सेल-आधारित स्क्रॉलिंग का उपयोग करता हूं, इसलिए यह मेरे लिए काम नहीं करता है, लेकिन मुझे यकीन है कि यह भविष्य में दूसरों की मदद करेगा, +1। –

+0

यदि आप पिक्सेल आधारित स्क्रॉलिंग का उपयोग कर रहे हैं तो आप आइटम्स कंट्रोल में किसी व्यक्तिगत आइटम का आकार प्राप्त कर सकते हैं (यदि यह एक निश्चित आकार है तो यह आसान है, लेकिन ऐसे आइटम भी हैं जो आप आइटमकंट्रोल आइटम टेम्पलेट पर कर सकते हैं ताकि व्यक्ति का आकार प्राप्त हो सके आइटम) और फिर केवल एक आइटम के आकार से लौटाए गए इंडेक्स को गुणा करें और फिर उस नंबर के साथ स्क्रॉलटॉवर्टिकलऑफसेट को कॉल करें। यानी sv.ScrollToVerticalOffset ((डबल) अनुक्रमणिका * आकार OfAnItemInTheList); –

0

मैं जानता हूँ कि मैं बहुत पार्टी के लिए देर हो रही है, लेकिन उम्मीद है कि इस मदद मिल सकती है किसी और समाधान की तलाश के साथ आ रहा है ...

int index = myItemsControl.Items.IndexOf(*your item*).FirstOrDefault(); 
int rowHeight = *height of your rows*; 
myScrollView.ScrollToVerticalOffset(index*rowHeight); 
//this will bring the given item to the top of the scrollViewer window 

... और मेरे XAML इस तरह सेटअप है ...

<ScrollViewer x:Name="myScrollView"> 
    <ItemsControl x:Name="myItemsControl"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Grid> 
        <!-- data here --> 
       </Grid> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ScrollViewer>