5

के लिए एमवीवीएम आर्किटेक्चर का उपयोग कर पीसीएल के अंदर व्यूमोडेल के भीतर आईएसयूपपोर्ट इंस्ट्रूमेंटलोडिंग लागू करता है, मेरे पास पीसीएल के अंदर मेरा व्यूमोडल्स है, क्योंकि मैं विंडोज 8.1 और विंडोज फोन ऐप को समानांतर में विकसित कर रहा हूं। मेरे पास व्यूमोडेल के अंदर एक अवलोकन योग्य चयन के रूप में चीजों की एक सूची है।निरीक्षण कोलेक्शन जो WinRT और WP8/WinPRT समर्थन

मेरे पास विंडोज 8.1 प्रोजेक्ट के अंदर एक पृष्ठ के अंदर एक ग्रिड व्यू है। मैं अपने व्यूमोडेल में अपनी चीजों की सूची से वस्तुओं को बढ़ाना चाहता हूं। आम तौर पर मैं ObservableCollection के कस्टम उप-वर्ग के अंदर ISupportIncrementalLoading को कार्यान्वित करता हूं, हालांकि, यह देखते हुए कि मेरा व्यूमोडेल एक पीसीएल के अंदर है, ISupportIncrementalLoading उपलब्ध नहीं है (यह WP8 द्वारा समर्थित नहीं है)।

तो मेरा सवाल यह है कि, क्या किसी के पास कोई सुझाव है कि मैं ग्रिड व्यू के आइटम्ससोर्स बाइंडिंग और मेरे व्यूमोडेल की अवलोकन योग्य संपत्ति के बीच किसी प्रकार का कनवर्टर, एडाप्टर या अमूर्त परत कैसे बना सकता हूं जो ISupportIncrementalLoading को लागू करेगा और फिर ViewModel की LoadMoreThings विधि को कॉल करें और आइटम को ग्रिड व्यू में पास करें।

मुझे लगता है कि कुछ समाधान हैं, जैसे कि मेरे व्यू मॉडल पीसीएल के अंदर एक कस्टम ISupportIncrementalLoading बनाना और उसके बाद व्यू लेयर प्रतिनिधि है।

धन्यवाद

उत्तर

16

अंत में, मैं सार कारखाने पैटर्न का इस्तेमाल किया। तथ्य हैं:

  • आप पीसीएल ViewModel परत से देखें परत संदर्भ नहीं दे सकता, के रूप में वी एम परत देखें परत के साथ संबंध नहीं होना चाहिए। इसका लाभ यह है कि आप लक्ष्य मंच पर किसी भी निर्भरता के बिना व्यूमोडेल परत का एक और उपभोक्ता बना सकते हैं। जैसे एक व्यूमोडेल लाइब्रेरी पीसीएल प्रोजेक्ट के पीछे एक विंडोज 8 और विंडोज फोन 8 ऐप बनाएं।

  • GridView एक WinRT घटक है जो ObservableCollection<T> से जुड़ सकता है। ObservableCollection<T>दोनों दृश्य परत और दृश्य मॉडल परत के अंदर उपलब्ध है। यदि आप अपने ऐप के अंदर बढ़ती लोडिंग का समर्थन करना चाहते हैं (जो बड़े डेटासेट के लिए जरूरी है), तो आपको ObservableCollection<T> का एक विशेष सबक्लास बनाना होगा जो ISupportIncrementalLoading लागू करता है। हम क्या चाहते हैं करना सिर्फ व्यूमोडेल प्रोजेक्ट के अंदर उस सबक्लास को बनाएं और आप कर चुके हैं। लेकिन हम यह नहीं कर सकते क्योंकि ISupportIncrementalLoading केवल एक WinRT प्रोजेक्ट के अंदर उपलब्ध है।

इस समस्या को अमूर्त कारखाने पैटर्न का उपयोग करके हल किया जा सकता है। सभी व्यूमोडेल वास्तव में ObservableCollection<T> चाहता है, लेकिन व्यू लेयर एक अवलोकन योग्य चयन की मांग करता है जो ISupportIncrementalLoading लागू करता है। तो जवाब ViewModel परत में एक इंटरफ़ेस को परिभाषित करना है जो व्यूमोडेल को सटीक रूप से देता है; आइए इसे IPortabilityFactory पर कॉल करें। फिर व्यू परत में IPortabilityFactory का ठोस कार्यान्वयन परिभाषित करें जिसे PortabilityFactory कहा जाता है। IPortabilityFactory (व्यू मॉडेल इंटरफ़ेस) को PortabilityFactory (देखें परत ठोस इत्यादि) पर मैप करने के लिए व्यू परत में आईओसी का उपयोग करें।

व्यूमोडेल क्लास के निर्माता पर, IPortabilityFactory उदाहरण इंजेक्शन दिया गया है। अब व्यूमोडेल में एक कारखाना है जो इसे ObservableCollection<T> उदाहरण देगा।

अब व्यूमोडेल में new ObservableCollection<Thing>() पर कॉल करने के बजाय आप factory.GetIncrementalCollection<Thing>(...) पर कॉल करते हैं।

ठीक है, तो हम ViewModel परत के साथ कर रहे हैं; अब हमें ObservableCollection<T> के उस कस्टम कार्यान्वयन की आवश्यकता है। इसे IncrementalLoadingCollection कहा जाता है और इसे व्यू परत में परिभाषित किया गया है। यह ISupportIncrementalLoading लागू करता है।

ISupportIncrementalLoading के कार्यान्वयन के साथ कोड और स्पष्टीकरण यहां दिए गए हैं।

व्यूमोडेल परत (पीसीएल) में मेरे पास एक सार कारखाना इंटरफ़ेस है।

public class PortabilityFactory : IPortabilityFactory 
{ 
    public ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete) 
    { 
     return new IncrementalLoadingCollection<T>(take, loadMoreItems, onBatchStart, onBatchComplete); 
    } 
} 

फिर, देखें परत के अंदर, मैं अपने आईओसी के लिए एकता का उपयोग करने के होती हैं:

public interface IPortabilityFactory 
{ 
    ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete); 
} 

देखें परत में (Windows 8 ऐप्स, इस मामले में) मैं इस तरह एक ठोस कारखाने को लागू । जब आईओसी बनाया जाता है, तो मैं पोर्टेबिलिटी फैक्ट्री (दृश्य परत में; ऐप प्रोजेक्ट) में आईपोर्टिबिलिटी फैक्ट्री (पीसीएल में) को मैप करता हूं।

Container.RegisterType<IPortabilityFactory, PortabilityFactory>(new ContainerControlledLifetimeManager()); 

अब हम ObservableCollection का एक उपवर्ग बनाने की जरूरत है और यहाँ कोड है:

    :

    public class IncrementalLoadingCollection<T> 
         : ObservableCollection<T>, ISupportIncrementalLoading 
        { 
         private Func<int, Task<List<T>>> _loadMoreItems = null; 
         private Action<List<T>> _onBatchComplete = null; 
         private Action _onBatchStart = null; 
    
    
         /// <summary> 
         /// How many records to currently skip 
         /// </summary> 
         private int Skip { get; set; } 
    
         /// <summary> 
         /// The max number of items to get per batch 
         /// </summary> 
         private int Take { get; set; } 
    
         /// <summary> 
         /// The number of items in the last batch retrieved 
         /// </summary> 
         private int VirtualCount { get; set; } 
    
         /// <summary> 
         /// .ctor 
         /// </summary> 
         /// <param name="take">How many items to take per batch</param> 
         /// <param name="loadMoreItems">The load more items function</param> 
         public IncrementalLoadingCollection(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete) 
         { 
          Take = take; 
          _loadMoreItems = loadMoreItems; 
          _onBatchStart = onBatchStart; 
          _onBatchComplete = onBatchComplete; 
          VirtualCount = take; 
         } 
    
         /// <summary> 
         /// Returns whether there are more items (if the current batch size is equal to the amount retrieved then YES) 
         /// </summary> 
         public bool HasMoreItems 
         { 
          get { return this.VirtualCount >= Take; } 
         } 
    
         public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) 
         { 
          CoreDispatcher dispatcher = Window.Current.Dispatcher; 
          _onBatchStart(); // This is the UI thread 
    
          return Task.Run<LoadMoreItemsResult>(
           async() => 
           { 
            var result = await _loadMoreItems(Skip); 
            this.VirtualCount = result.Count; 
            Skip += Take; 
    
            await dispatcher.RunAsync(
             CoreDispatcherPriority.Normal, 
             () => 
             { 
              foreach (T item in result) this.Add(item); 
              _onBatchComplete(result); // This is the UI thread 
             }); 
    
            return new LoadMoreItemsResult() { Count = (uint)result.Count }; 
    
           }).AsAsyncOperation<LoadMoreItemsResult>(); 
         } 
        } 
    

    IncrementalLoadingCollection के निर्माता चार मापदंडों जो कारखाने के माध्यम से ViewModel द्वारा आपूर्ति की जाएगी के लिए पूछता है

  • ले लो - यह पृष्ठ का आकार

  • loadMoreItems - इस ViewModel के अंदर एक समारोह है कि आइटम के अगले बैच को पुनः प्राप्त (महत्वपूर्ण बात, इस समारोह यूआई धागा अंदर नहीं चलेंगे)

  • onBatchStart जाएगा के लिए एक प्रतिनिधि संदर्भ है - यह सिर्फ loadMoreItems से पहले सक्रिय किया जाएगा विधि कहा जाता है। यह मुझे ViewModel पर गुणों में परिवर्तन करने की अनुमति देता है जो दृश्य को प्रभावित कर सकता है। उदाहरण के लिए, एक अवलोकन योग्य IsProcessing संपत्ति है जो प्रगति पट्टी की दृश्यता संपत्ति से जुड़ी है।

  • ऑनबैचकंपलेट - यह नवीनतम बैच की पुनर्प्राप्ति के बाद ही इन्हें बुलाया जाएगा और आइटम पास कर देगा। महत्वपूर्ण रूप से, यह फ़ंक्शन यूआई थ्रेड पर आ जाएगा।

    public const string IsProcessingPropertyName = "IsProcessing"; 
    
    private bool _isProcessing = false; 
    public bool IsProcessing 
    { 
        get 
        { 
         return _isProcessing; 
        } 
        set 
        { 
         if (_isProcessing == value) 
         { 
          return; 
         } 
         RaisePropertyChanging(IsProcessingPropertyName); 
         _isProcessing = value; 
         RaisePropertyChanged(IsProcessingPropertyName); 
         } 
    } 
    
        private IPortabilityFactory _factory = null; 
        public ViewModel(IPortabilityFactory factory) 
        { 
         _factory = factory; 
         Initialize(); 
        } 
    
    
        private async void Initialize() 
        { 
         Things = _factory.GetIncrementalCollection<Thing>(10, LoadThings, 
          () => IsProcessing = true, BatchLoaded); 
        } 
    
        private void BatchLoaded(List<Thing> batch) 
        { 
         IsProcessing = false; 
        } 
    
        private async Task<List<Thing>> LoadThings(int skip) 
        { 
         var items = await _service.GetThings(skip, 10 /*page size*/); 
         return items; 
        } 
    

    मुझे आशा है कि यह किसी को मदद मिलती है:

ViewModel परत में, मेरा ViewModel उस पर एक निर्माता है जो एक IPortabilityFactory वस्तु को स्वीकार करता है।

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