2016-07-11 14 views
13

के साथ ScrollIntoView और ListView मेरे पास ListView (वर्चुअलाइजेशन डिफ़ॉल्ट रूप से चालू है), जो ItemsSourceObservableCollection<Item> संपत्ति से जुड़ा हुआ है।वर्चुअलाइजेशन

जब डेटा पॉप्युलेट किया जाता है (संपत्ति सेट हो जाती है और अधिसूचना बढ़ी जाती है) मैं प्रोफाइलर में 2 लेआउट स्पाइक देखता हूं, दूसरा listView.ScrollIntoView() पर कॉल करने के बाद होता है।

मेरे समझ है: बंधन के माध्यम से

  1. ListView लोड डेटा और स्क्रीन पर आइटम, सूचकांक 0.
  2. से शुरू तो मैं listView.ScrollIntoView() फोन के लिए ListViewItem पैदा करता है।
  3. और अब ListView वह दूसरी बार करता है (ListViewItem एस बना रहा है)।

मैं उस डी-वर्चुअलाइजेशन को दो बार होने से कैसे रोकूं (मुझे ScrollIntoView होने से पहले एक नहीं चाहिए)?


मैंने ListBox का उपयोग करके एक रेपो बनाने की कोशिश की।

XAML:

<Grid> 
    <ListBox x:Name="listBox" ItemsSource="{Binding Items}"> 
     <ListBox.ItemContainerStyle> 
      <Style TargetType="ListBoxItem"> 
       <Setter Property="IsSelected" Value="{Binding IsSelected}" /> 
      </Style> 
     </ListBox.ItemContainerStyle> 
    </ListBox> 
    <Button Content="Fill" VerticalAlignment="Top" HorizontalAlignment="Center" Click="Button_Click" /> 
</Grid> 

सीएस:

public class NotifyPropertyChanged : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged([CallerMemberName] string property = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 
} 

public class ViewModel : NotifyPropertyChanged 
{ 
    public class Item : NotifyPropertyChanged 
    { 
     bool _isSelected; 
     public bool IsSelected 
     { 
      get { return _isSelected; } 
      set 
      { 
       _isSelected = value; 
       OnPropertyChanged(); 
      } 
     } 
    } 

    ObservableCollection<Item> _items = new ObservableCollection<Item>(); 
    public ObservableCollection<Item> Items 
    { 
     get { return _items; } 
     set 
     { 
      _items = value; 
      OnPropertyChanged(); 
     } 
    } 
} 

public partial class MainWindow : Window 
{ 
    ViewModel _vm = new ViewModel(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = _vm; 
    } 

    void Button_Click(object sender, RoutedEventArgs e) 
    { 
     var list = new List<ViewModel.Item>(1234567); 
     for (int i = 0; i < 1234567; i++) 
      list.Add(new ViewModel.Item()); 
     list.Last().IsSelected = true; 
     _vm.Items = new ObservableCollection<ViewModel.Item>(list); 
     listBox.ScrollIntoView(list.Last()); 
    } 
} 

डीबग - प्रदर्शन प्रोफाइलर - आवेदन समय ... थोड़ा इंतज़ार, बटन पर क्लिक करें, एक सा, खिड़की बंद प्रतीक्षा करें। आपको VirtualizingStackPanel के साथ 2 लेआउट पास दिखाई देंगे। मेरा लक्ष्य सिर्फ एक है और मुझे नहीं पता कि कैसे।

रेपो के साथ समस्या भार को अनुकरण करना है (ListViewItemis expensive बनाते समय), लेकिन मुझे आशा है कि यह अब और अधिक स्पष्ट रूप से समस्या का प्रदर्शन करेगा।

+0

क्या आप हमेशा यूआई में आइटमों को संग्रहित करने के बाद आखिरी वस्तु को देखने के लिए चाहते हैं? यह दो लेआउट पासों के मुद्दे को हल नहीं करता है, लेकिन यदि ऐसा है तो आप संभावित रूप से बदल सकते हैं कि उन्हें UI में जोड़ने से पहले आइटम कैसे क्रमबद्ध किए जाते हैं ताकि आप जिस आइटम को देखना चाहते हैं वह संग्रह में पहला आइटम है – Bijington

+0

@ बीजिंगटन, संग्रह पहले ही सॉर्ट किया गया है (तिथि तक, एमसीवी में नहीं दिखाया गया है), मुझे ऑर्डर नहीं बदलना चाहिए। यह कोई भी आइटम हो सकता है (वास्तविक प्रोजेक्ट में यह बहु-चयन 'सूची दृश्य' है, अंतिम चयनित आइटम पर स्क्रॉल कर रहा है)।आदर्श रूप से मैं एमवीवीएम अनुप्रयोग में 'लिस्ट व्यू' राज्य को स्टोर/पुनर्स्थापित करने के तरीके की तलाश कर रहा हूं (चयन को संभाला जाता है, लेकिन स्क्रॉल स्थिति नहीं है, यह * किसी भी तरह * 'स्क्रॉलइनो व्यू' के साथ संभाला जाता है), कि डबल डी-वर्चुअलाइजेशन एक्सवाई- समस्या (लेकिन मैं 'ScrollIntoView' के साथ ठीक हूं, केवल डी-वर्चुअलाइजेशन दो बार समस्या है)। – Sinatr

+0

मैंने उतना ही माना लेकिन मैंने सोचा कि यह एक पूछने लायक था। यह निश्चित रूप से हल करने के लिए एक दिलचस्प समस्या की तरह लगता है। किसी भी तरह की सामग्री को लोड करने से पहले आपको 'ListView' की स्क्रॉल स्थिति को बताना होगा। क्या आप किसी भी प्रकार 'ListView' को उपclass कर सकते हैं और जब तक आप लोड पास (शायद एक IsLoadingContent ध्वज) समाप्त नहीं कर लेते हैं तो प्रतिपादन को रोक सकते हैं ताकि आप आइटम असाइन कर सकें और यह भी चिह्नित कर सकें कि किस आइटम को चुना जाना चाहिए और दृश्य में लाया गया है? – Bijington

उत्तर

0

स्क्रॉल विधियां आमतौर पर VirtualizingStackPanel पर बहुत अच्छी तरह से काम नहीं करती हैं। इसके आसपास काम करने के लिए मैं निम्नलिखित समाधान का उपयोग करता हूं।

  1. VirtualizingStackPanel डुबोएं। पैनल टेम्पलेट के लिए सामान्य स्टैकपैनल के साथ जाएं।
  2. अपने डेटा टेम्पलेट की बाहरी परत को यहां से LazyControl बनें: http://blog.angeloflogic.com/2014/08/lazycontrol-in-junglecontrols.html
  3. सुनिश्चित करें कि आप उस LazyControl पर ऊंचाई निर्धारित करते हैं।

मुझे आम तौर पर उस दृष्टिकोण से अच्छा प्रदर्शन मिलता है। यह वही करने के लिए जो आप पूछ रहे हैं, आपको कुछ ध्वज सेट करने के लिए LazyControl में कुछ अतिरिक्त तर्क जोड़ने की आवश्यकता हो सकती है (स्क्रॉल विधि को कॉल करने के बाद)।

संबंधित मुद्दे