2013-08-03 94 views
1

這是一個基本的MVVM問題。MVVM模型責任

假設我有一個學生編輯窗口,允許用戶設置學生的付款方式(現金或支票)。爲了靈活性,必須從服務器檢索可能的支付方法,並且該列表根據學生的年齡而變化,這也可以改變。

的問題是:

  1. 應該在哪裏存放可能支付方法?模型還是視圖模型?

  2. if model,當用戶更改年齡誰應該下載新的付款方式列表?

MVVM應該包含什麼模型?

+0

那麼誰來決定爲特定學生選擇的支付方式是否有效,服務器還是學生本身? –

回答

1

那麼,在我看來,模型應該包含支付方法的列表,而虛擬機應該包含一個列表綁定到視圖。例如,我要做的是在模型上有List<PaymentOptions>,對於VM有BindingList<PaymentOptions>ObservableCollection<PaymentOptions>

+0

嗨,我更新了問題以使付款方式變爲動態 – LostInComputer

+0

您仍然可以擁有付款方式列表,並且這些付款方式擁有適合年齡的財產嗎?然後在VM中選擇列表中的項目。示例: List _paymentMethods; BindingList _possiblemethods = _paymentMethods.Where(x => x.Age> minimum_age) –

2

該模型是容納付款方法和與每種方法相關聯的業務規則的邏輯地點。一種方法是使用描述每種支付方法的枚舉,並使用'switch'語句來查詢。

另一種設計融合多態性的優勢,可能是這樣的......

public class Model 
{ 
    private readonly List<PaymentMethod> _allPaymentMethods; 
    public Model() 
    { 
     // get payment types from the db 
     // to populate master list 
     _allPaymentMethods = new List<PaymentMethod> {new Cash(), new CreditCard()}; 
    } 
    public List<PaymentMethod> GetPaymentMethods(int age) 
    { 
     List<PaymentMethod> result = 
      _allPaymentMethods.Where(q => q.Age == age).ToList(); 
     return result; 
    } 
} 
public abstract class PaymentMethod 
{ 
    public string Name { get; protected set; } 
    public int Age { get; protected set; } 
    public abstract void ProcessPayment(); 
    public override string ToString() 
    { 
     return Name; 
    } 
} 
public class CreditCard:PaymentMethod 
{ 
    public CreditCard() 
    { 
     Name = "Credit Card"; 
     Age = 25; 
    } 
    public override void ProcessPayment() 
    { 
     Console.WriteLine("Thanks for using your card"); 
    } 
} 
public class Cash:PaymentMethod 
{ 
    public Cash() 
    { 
     Name = "Cash"; 
     Age = 22; 
    } 
    public override void ProcessPayment() 
    { 
     Console.WriteLine("Thanks for paying cash"); 
    } 
} 

此示例硬編碼兩種方法:現金及信用卡,並且每一類都知道該怎麼做了工作,而依靠繼承來處理共同的屬性。這種方法避免了「轉換」,並封裝了每個類中的所有業務規則和方法。因此,該模型只公開ViewModel需要知道的內容,以便在項目控件中向用戶展示各種支付方法。

當用戶更改其年齡時,您的VM可以刷新列表。

的VM代碼片斷看起來像......

public class ViewModel :INotifyPropertyChanged 
{ 
    public ObservableCollection<PaymentMethod> Methods { get; set; } 
    public ViewModel() 
    { 
     Model m = new Model(); 
     Methods = new ObservableCollection<PaymentMethod>(m.GetPaymentMethods(22)); 
    } 
    #region INotifyPropertyChanged Implementation 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected virtual void OnPropertyChanged(string name) 
    { 
     var handler = System.Threading.Interlocked.CompareExchange 
       (ref PropertyChanged, null, null); 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    #endregion 
} 

無論接近你使用(無論是枚舉或多態性),經驗法則是「是否VM絕對需要知道嗎?能我將繼承和多態的OO優勢用於我的架構?「

+0

此模型是否還包含學生屬性或者是由VM管理的自己模型中的學生? – LostInComputer

+0

@LostInComputer,我嘗試在我的設計中實現高水平的隔離,因爲它簡化了測試和嘲諷。所以我會對學生使用相同的方法,即將業務規則放入模型中並儘可能少地暴露給虛擬機。單元測試模型,並將其模擬出來以測試虛擬機。 –