2011-10-17 16 views
5

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

वैसे भी, मेरी समस्या यह है कि मैं प्रत्येक आगामी पृष्ठ को वापस करने के लिए एक आईनेमरेबल का उपयोग कर रहा हूं, जो वास्तव में बहुत अच्छा काम करता है, लेकिन मुझे पता है कि मैं शायद भाषा के साथ कुछ अनुचित/अनपेक्षित कर रहा हूं। बच्चे वर्ग केवल सार कदम IEnumerable एक्सेसर ओवरराइड करने के लिए है:

public class HPLDTWizardViewModel : WizardBase 
{ 
    protected override IEnumerable<WizardStep> Steps 
    { 
    get 
    { 
     WizardStep currentStep; 

     // 1.a start with assay selection 
     currentStep = new AssaySelectionViewModel(); 
     yield return currentStep; 
     // 1.b return the selected assay. 
     SigaDataSet.Assay assay = ((AssaySelectionViewModel)currentStep).SelectedAssay; 
     sigaDataSet = (SigaDataSet)assay.Table.DataSet; 

     // 2.a get the number of plates 
     currentStep = new NumPlatesViewModel(sigaDataSet); 
     yield return currentStep; 
     ... 
    } 
    } 
} 

माता पिता वर्ग कदम का उपयोग कर नेविगेशन तर्क होता है विशेषताओं 'प्रगणक:

public abstract class WizardBase : ViewModelBase 
{ 
    private ICommand _moveNextCommand; 
    private ICommand _cancelCommand; 
    private IEnumerator<WizardStep> _currentStepEnumerator; 

    #region Events 

    /// <summary> 
    /// Raised when the wizard window should be closed. 
    /// </summary> 
    public event EventHandler RequestClose; 

    #endregion // Events 

    #region Public Properties 

    /// <summary> 
    /// Gets the steps. 
    /// </summary> 
    /// <value>The steps.</value> 
    protected abstract IEnumerable<WizardStep> Steps { get;} 

    /// <summary> 
    /// Gets the current step. 
    /// </summary> 
    /// <value>The current step.</value> 
    public WizardStep CurrentStep 
    { 
    get 
    { 
     if (_currentStepEnumerator == null) 
     { 
     _currentStepEnumerator = Steps.GetEnumerator(); 
     _currentStepEnumerator.MoveNext(); 
     } 

     return _currentStepEnumerator.Current; 
    } 
    } 

    #endregion //Public Properties 

    #region Commands 

    public ICommand MoveNextCommand 
    { 
    get 
    { 
     if (_moveNextCommand == null) 
     _moveNextCommand = new RelayCommand(
      () => this.MoveToNextPage(), 
      () => this.CanMoveToNextPage()); 

     return _moveNextCommand; 
    } 
    } 

    public ICommand CancelCommand 
    { 
    get 
    { 
     if (_cancelCommand == null) 
     _cancelCommand = new RelayCommand(() => OnRequestClose()); 

     return _cancelCommand; 
    } 
    } 

    #endregion //Commands 

    #region Private Helpers 

    /// <summary> 
    /// Determines whether this instance [can move to next page]. 
    /// </summary> 
    /// <returns> 
    /// <c>true</c> if this instance [can move to next page]; otherwise, <c>false</c>. 
    /// </returns> 
    bool CanMoveToNextPage() 
    { 
    if (CurrentStep == null) 
     return false; 
    else 
     return CurrentStep.IsValid(); 
    } 

    /// <summary> 
    /// Moves to next page. 
    /// </summary> 
    void MoveToNextPage() 
    { 
    _currentStepEnumerator.MoveNext(); 

    if (_currentStepEnumerator.Current == null) 
     OnRequestClose(); 
    else 
     OnPropertyChanged("CurrentStep"); 
    } 

    /// <summary> 
    /// Called when [request close]. 
    /// </summary> 
    void OnRequestClose() 
    { 
    EventHandler handler = this.RequestClose; 
    if (handler != null) 
     handler(this, EventArgs.Empty); 
    } 

    #endregion //Private Helpers 
} 

और यहाँ WizardStep सार वर्ग है जो प्रत्येक विज़ार्ड पेज लागू:

public abstract class WizardStep : ViewModelBase 
{ 
    public abstract string DisplayName { get; } 

    public abstract bool IsValid(); 

    public abstract List<string> GetValidationErrors(); 
} 

जैसा कि मैंने कहा, यह आश्चर्यजनक रूप से काम करता है क्योंकि मैं संख्याकर्ता के साथ सूची में नेविगेट करता हूं। नेविगेशन तर्क एक अमूर्त माता-पिता वर्ग में है और सभी बच्चे को कदम विशेषता को ओवरराइड करना है। विज़ार्डस्टेप्स में स्वयं तर्क शामिल होते हैं ताकि वे जान सकें कि वे कब वैध हैं और उपयोगकर्ता जारी रख सकते हैं। मैं एमवीवीएम का उपयोग कर रहा हूं, इसलिए अगला बटन कमांड के माध्यम से CanMoveToNextPage() और MoveToNextPage() फ़ंक्शंस से जुड़ा हुआ है।

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

+1

इस ब्लॉग पोस्ट पर एक नज़र डालें http://blogs.msdn.com/b/shawnhar/archive/2010/10/01/iterator-state-machines.aspx – asawyer

+1

'_currentStepEnumerator' क्या है? खैर, मुझे कल्पना है कि यह एक 'आईएन्यूमेरेटर' है लेकिन क्या आप कृपया यह स्पष्ट कर सकते हैं कि इसे कैसे घोषित किया जाता है? क्या यह एक स्थिर सदस्य है? अंत में, मुझे आपके कोड के साथ कुछ भी बुरा नहीं दिख रहा है: यदि यह आपके एप्लिकेशन तर्क को सरल बनाता है तो मुझे पूरा यकीन है कि आप इसका उपयोग कर सकते हैं। वैसे भी अच्छा सवाल :) –

+0

पूर्ण जादूगरबेस वर्ग के साथ अद्यतन किया गया। आपकी सहायक टिप्पणियों के लिए धन्यवाद! – millejos

उत्तर

1

मुझे लगता है कि जब तक कुछ आवश्यकताओं को पूरा करता है, तब तक बनाए रखना आसान है और पढ़ने में आसान है, तो यह बुरा नहीं हो सकता है।

जाहिर है जैसा आपने अनुमान लगाया है कि यह आईनेमेरेबल का शास्त्रीय उपयोग नहीं है। लेकिन, इस तरह की ऑफ-बीट स्थितियों के लिए उपज रिटर्न लगभग हमेशा उपयोग किया जाता है (कम से कम मेरे अनुभव में)। जब तक आपको "< बैक" समर्थन की आवश्यकता नहीं होगी, तब तक मैं समाधान को छोड़ दूंगा।

विकल्पों के लिए, मैंने कई दृष्टिकोणों का उपयोग किया है, कोई भी वास्तव में मेरे स्वाद के लिए नहीं है। ब्रांचिंग पथ वाले जादूगर हमेशा कठोर गन्दा होते हैं।

हेवीवेट जादूगरों के लिए, एक विकल्प एक राज्य मशीन है। एक या दो तरीकों को लिखें जो जानता है कि राज्यों के बीच कैसे चलना है, और कौन से संक्रमण मान्य हैं। प्रत्येक राज्य के लिए UserControl बनाएं और उन्हें ListCollectionView के माध्यम से TabControl पर बेनकाब करें।

एक अच्छा हल्का समाधान जिसे मैंने एक बार इस्तेमाल किया था, एक ग्रिड में एक-दूसरे के ऊपर विज़ार्ड में सभी पृष्ठों को ढेर करना और गणना के प्रतिनिधित्व वाले राज्य को बाध्य करके अपनी दृश्यता टॉगल करना है। ValueConverter का उपयोग करके आप जादू संख्याओं से भी बच सकते हैं। पृष्ठों के बीच स्विचिंग बस स्थिति संपत्ति में वृद्धि या कमी का मामला बन जाता है।

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