2011-12-17 15 views
2

私は最近SilverlightでMVVMパターンの使用を開始しました。正しく使用しているかどうかはわかりません。私のICommandのロジックはどこに置くのですか?

GUI

私は現在、株式市場部門のコンボボックスを持っているMAINVIEWを持っています。ユーザーがセクター(例えばENERGY)を選択し、追加ボタンをクリックすると、そのセクターの在庫のリストがリストボックスに表示されます。リストボックスの各在庫の横には、リストボックスから個々の在庫を削除するための削除ボタンがあります。

次のViewModelを実装しました。 (下はコードの一例です)

public class MainViewModel 
{ 
    public SectorViewModel CurrentSector 
    { 
    get; 
    set; 
    } 

    public string SelectedSector 
    { 
    get; 
    set; 
    } 


    public void AddSectorClickedCommand() 
    { 
    CurrentSector = new SectorViewModel(SelectedSector); 
    } 

} 

public class SectorViewModel 
{ 
    public ObservableCollection<StockViewModel> Stocks = new ObservableCollection<StockViewModel>(); 

    public SectorViewModel(string sector) 
    { 
     List<Stocks> stocklist = StockProvider.GetStocks(sector); 
     for each (var s in stocklist) 
     { 
      StockViewModel svm = new StockViewModel(s); 
      svm.Remove+= { //Remove svm from Stocks collection logic 
      Stocks.add(svm); 

     } 
    } 
} 

私の質問は次のとおりです。 viewmodelでは、リストボックスの各行のRemoveボタンのコード実装を追加するのが最も良いでしょうか? [削除]ボタンをクリックすると、SectorViewModel.StocksコレクションからStockViewModelが削除されます。

私は現在、StockViewModelにRemoveClickedメソッドを追加しています(上記参照)。このコードはイベントをSectorViewModelに戻し、SectorViewModelのRemoveStockメソッドはStockViewModelをStockコレクションから削除します。

この削除機能を実装するより良い方法はありますか?私はMVVMが新しく、SectorViewModelがStockViewModelのイベントに登録する必要があるため、これがこの機能性を開発する最良の方法であるかどうかはわかりません。

+1

私のデザインはこれがここで何が行われているので大丈夫と思われます。http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090016 – caa

答えて

0

私は個人的にイベントを好きではありません。なぜなら、イベントの購読を中止する必要があり、適切でない場所で使用できるからです。

私はこのような何か、削除コマンドを処理するために、コンストラクタのパラメータを使用します。

public class StockViewModel 
{ 
    public StockViewModel(Stock stock, Action<StockViewModel> removeCommandAction) 
    { 
     //... 
     this.RemoveCommand = new DelegateCommand(() => removeCommandAction(this)); 
    } 
} 

public class SectorViewModel 
{ 
    public SectorViewModel() 
    { 
     //... 
     StockViewModel svm = new StockViewModel(s, this.RemoveStock); 
     Stocks.add(svm); 
    } 

    private void RemoveStock(StockViewModel stock) 
    { 
     //... 
    } 
} 

別のアプローチは、MVVM光ツールキットから、例えば、MessengerクラスをEventAggregatorパターンのいくつかの種類を使用することです。しかし、私は、それは、そのような単純な作業のためにやり過ぎだと思い:

public StockViewModel(Stock stock, IMessenger messenger) 
{ 
    //... 
    this.RemoveCommand = new DelegateCommand(() => 
     messenger.Send(new NotificationMessage<StockViewModel>(this, RemoveItemNotification))); 
} 

public SectorViewModel(IMessenger messenger) 
{ 
    //... 
    messenger.Register<NotificationMessage<StockViewModel>>(this, msg => 
    { 
     if (msg.Notification == StockViewModel.RemoveItemNotification) 
     { 
      this.RemoveStock(msg.Content); 
     } 
    } 
} 

また、私はシルバー5は相対的なソースへのバインディングをサポートすることを聞きました。 3番目のアプローチがあります。私は、この例が動作するかどうかわからないんだけど、少なくともそれはすべき:

<Button Content="Remove" 
    Command="{Binding DataContext.RemoveCommand RelativeSource={RelativeSource AncestorType=ListBox}}" 
    CommandParameter="{Binding}" /> 
public class SectorViewModel 
{ 
    public SectorViewModel() 
    { 
     this.RemoveCommand = new DelegateCommand(obj => this.RemoveStock((StockViewModel)obj)); 
    } 

    public ICommand RemoveCommand { get; set; } 
} 

最後の例は、ほとんどの方法によって好まれるとWPFは常にRelativeSourceバインディングを持っていたので、WPFアプリケーションで使用されています。

関連する問題