2011-12-17 133 views
2

我最近开始在silverlight中使用MVVM模式,并且我不确定我是否正确使用它。我在哪里放置ICommand的逻辑?

GUI

我现在有有股市行业组合框一个的MainView。当用户选择一个扇区(例如能源)并点击添加按钮时,该扇区的股票列表将显示在列表框中。在列表框中的每个股票的边上都有一个删除按钮,允许您从列表框中删除单个股票。

我已经实现了以下ViewModels。 (下面仅仅是代码的指示)

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); 

     } 
    } 
} 

我的问题是;在视图模型中,最好为列表框中每行的Remove按钮添加代码实现?删除按钮应该从SectorViewModel.Stocks集合中删除StockViewModel。

我目前已将RemoveClicked方法添加到StockViewModel(如上所示)。此代码将事件触发回SectorViewModel,并且SectorViewModel的RemoveStock方法从Stock集合中删除StockViewModel。

是否有更好的方法来实现这个删除功能?我是MVVM的新手,并不确定这是否是开发此功能的最佳方法,因为SectorViewModel需要注册到StockViewModel的事件。

+1

我的设计似乎没问题,因为这也是什么在这里做了什么http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090016 – caa 2011-12-17 14:27:09

回答

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) 
    { 
     //... 
    } 
} 

另一种方法是使用某种类型的EventAggregator模式,例如,从MVVM光工具包Messenger类。但我认为这是这样简单的任务矫枉过正:

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); 
     } 
    } 
} 

而且我听说的Silverlight 5支持绑定到一个相对的发射源。 所以有第三种方法。我不知道这是否如工作,但它至少应该:

<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应用程序的使用,因为WPF一直都有的RelativeSource约束力。