2016-06-29 11 views
6

मैं अपने डब्ल्यूपीएफ एप्लिकेशन के साथ प्रदर्शन में सुधार करने की कोशिश कर रहा हूं और मुझे जटिल आइटम नियंत्रण के साथ समस्याएं आ रही हैं। हालांकि मैंने वर्चुअलाइजेशन जोड़ा है, फिर भी एक प्रदर्शन समस्या है और मुझे लगता है कि मैंने क्यों काम किया है।क्या छिपे पैनलों या विस्तारकों के साथ वर्चुअलाइजेशन का उपयोग करने का कोई तरीका है?

प्रत्येक आइटम में विस्तार योग्य क्षेत्रों की श्रृंखला शामिल है। तो उपयोगकर्ता शुरुआत में सारांश देखता है लेकिन अधिक जानकारी देखने के लिए विस्तार करके ड्रिल कर सकता है। यह इस प्रकार से दिखाई देता है:

enter image description here

आप देख सकते हैं, वहाँ कुछ नेस्टेड ItemsControls है। तो शीर्ष स्तर के प्रत्येक आइटम में छिपे हुए नियंत्रणों का एक गुच्छा है। वर्चुअलाइजेशन ऑफ-स्क्रीन आइटम्स को लोड होने से रोकता है, लेकिन आइटम के भीतर छिपा वस्तुओं को स्वयं नहीं रोकता है। नतीजतन, अपेक्षाकृत सरल प्रारंभिक लेआउट एक महत्वपूर्ण समय लेता है। इनमें से कुछ विचारों के चारों ओर झुकाव, 87% समय पार्सिंग और लेआउट खर्च किया जाता है, और इसे लोड करने में कुछ सेकंड लगते हैं।

मैं पूरे पृष्ठ को लोड करने के लिए 2s की बजाय, (if!) उपयोगकर्ता के निर्णय लेने के लिए 200ms लेना चाहता हूं।

वास्तव में सलाह मांगना। हालांकि मैं एमवीवीएम का उपयोग कर नियंत्रण जोड़ने का एक अच्छा तरीका नहीं सोच सकता। क्या कोई विस्तारक, या दृश्यता आधारित वर्चुअलाइजेशन डब्ल्यूपीएफ में समर्थित है या क्या मैं अपना खुद का कार्यान्वयन कर रहा हूं?

87% आंकड़ा निदान से आता है:

enter image description here

+1

* "आइटमों के भीतर छिपा वस्तुओं" * क्या है? वर्चुअलाइजेशन ['ContentPresenter'] (http://stackoverflow.com/a/12437064/1997232) नहीं बनाएगा, लेकिन कहीं आपके पास 'ऑब्जर्जेबल कोलेक्शन <>' है जिसे पूरी तरह से लोड किया जाना है। तो, इस '2 एस' में क्या शामिल है? क्या आपने यह देखने के लिए प्रोफाइलिंग की है कि वास्तव में एक बाधा क्या है? – Sinatr

+0

क्या आप आइटम का हिस्सा वर्चुअलाइज़ करना चाहते हैं जो 'विस्तारक '(निर्मित वस्तुओं के लिए) के अंदर है? यदि हां, तो आप ViewModel में संक्षिप्त स्थिति को ** ** विस्तारित करते समय अधिक डेटा जोड़ सकते हैं (उदाहरण के लिए 'ऑब्जेक्ट' का उपयोग करके डेटा और डेटा-टेम्पलेट को पकड़ने के लिए कुछ दृश्य बनाने के लिए 'शून्य' नहीं)। – Sinatr

+0

इस तरह यह लेआउट करता है। जब तक यह खुला नहीं होता तब तक आप डेटा प्राप्त करने में देरी कर सकते हैं। मुझे आश्चर्य है कि 2 सेकंड लगते हैं। – Paparazzi

उत्तर

5

तो आप बस

- Expander 
     Container 
      some bindings 
    - Expander 
      Container 
       some bindings 
+ Expander 
+ Expander 
... invisible items 

तो हाँ, Container और सभी बाइंडिंग पल में प्रारंभ कर रहे हैं जब दृश्य दिखाया जाता है (और ItemsControl दृश्यमान वस्तुओं के लिए ContentPresenter बनाता है)।

आप Expander जब वह संकुचित हो रहा है की सामग्री virtualize करने के लिए चाहते हैं, तो आप डेटा-templating का उपयोग कर सकते

public ObservableCollection<Item> Items = ... // bind ItemsControl.ItemsSource to this 

class Item : INotifyPropertyChanged 
{ 
    bool _isExpanded; 
    public bool IsExpanded // bind Expander.IsExpanded to this 
    { 
     get { return _isExpanded; } 
     set 
     { 
      Data = value ? new SubItem(this) : null; 
      OnPropertyChanged(nameof(Data)); 
     } 
    } 

    public object Data {get; private set;} // bind item Content to this 
} 

public SubItem: INotifyPropertyChanged { ... } 

मुझे आशा है कि कैसे करने के लिए XAML में SubItem के डेटा-templating करने के लिए समझाने के लिए कोई जरूरत नहीं है।

यदि आप ऐसा करते हैं तो शुरुआत में Data == null और Expander को छोड़कर कुछ भी लोड नहीं होता है। जैसे ही इसे विस्तारित किया जाता है (उपयोगकर्ता या प्रोग्रामेटिक रूप से) दृश्य दृश्य बना देगा।

+0

टेम्पलेट का उपयोग करना एक अच्छा विचार है, मैंने इसे बहुत अधिक लागू किया है कि आप कैसे वर्णन करते हैं और प्रदर्शन में काफी सुधार हुआ है। धन्यवाद! – Joe

1

मैंने सोचा कि मैं समाधान का ब्योरा डालूंगा, जो सिनाटर के जवाब का काफी प्रत्यक्ष कार्यान्वयन है।

मैंने एक बहुत ही सरल डेटा टेम्पलेट चयनकर्ता के साथ सामग्री नियंत्रण का उपयोग किया। टेम्पलेट चयनकर्ता बस अगर सामग्री मद रिक्त है की जाँच करता है, और दो डेटा टेम्पलेट्स के बीच चुनता है:

public class VirtualizationNullTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate NullTemplate { get; set; } 
    public DataTemplate Template { get; set; } 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     if (item == null) 
     { 
      return NullTemplate; 
     } 
     else 
     { 
      return Template; 

     } 
    } 
} 

इस का कारण यह है कि ContentControl मैं इस्तेमाल किया अभी भी डेटा टेम्पलेट भले ही सामग्री रिक्त है बाहर देता है।इसलिए मैं XAML में इन दो टेम्पलेट्स सेट:

  <ContentControl Content="{Binding VirtualizedViewModel}" Grid.Row="1" Grid.ColumnSpan="2" ><!--Visibility="{Binding Expanded}"--> 
       <ContentControl.Resources> 
        <DataTemplate x:Key="Template"> 
         <StackPanel> 
          ...complex layout that isn't often seen... 
         </StackPanel> 
        </DataTemplate> 
        <DataTemplate x:Key="NullTemplate"/> 
       </ContentControl.Resources> 
       <ContentControl.ContentTemplateSelector> 
        <Helpers:VirtualizationNullTemplateSelector Template="{StaticResource Template}" NullTemplate="{StaticResource NullTemplate}"/> 
       </ContentControl.ContentTemplateSelector> 
      </ContentControl> 

अंत में, बल्कि एक उप आइटम के लिए एक पूरी नई वर्ग का उपयोग करने से, यह आपके विचार मॉडल में एक "VirtualizedViewModel" वस्तु का संदर्भ देता है "इस बनाने के लिए बहुत आसान है ":

private bool expanded; 
    public bool Expanded 
    { 
     get { return expanded; } 
     set 
     { 
      if (expanded != value) 
      { 
       expanded = value; 
       NotifyOfPropertyChange(() => VirtualizedViewModel); 
       NotifyOfPropertyChange(() => Expanded); 
      } 
     } 
    } 


    public MyViewModel VirtualizedViewModel 
    { 
     get 
     { 
      if (Expanded) 
      { 
       return this; 
      } 
      else 
      { 
       return null; 
      } 
     } 
    } 

मैंने 2-3 के लोडिंग समय को लगभग 75% तक कम कर दिया है और अब यह अधिक उचित लगता है।

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

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