MVVM在模型中命令是一种不好的做法?

Iva*_*nko 1 c# wpf mvvm mvvm-light

我想知道,将命令放入模型是MVVM中的不良做法.例如,我有ListBoxImageButton.当我点击时Button我需要在浏览器中打开网址.所以,我的代码看起来像这样:

<ListBox ItemSource="{Binding Items">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source={Binding ImageSource} />
                <Button Content="Open url" Command={Binding OpenUrlCommand}"/>
            </StackPanel>
        </DataTemplate>
    </Listbox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)

视图模型:

class MainViewModel:BaseViewModel
{
    public ObservableCollection<Model> Items {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

模型:

class Model
{
    public string ImageSource {get;set;}

    public string Url {get;set;}

    public ICommand OpenUrlCommand {get;set;}

    public Model()
    {
       OpenUrlCommand = new RelayCommand(openUrl);
    }

    public void openUrl()
    {
        Process.Start(Url); //Open url in browser
    }
}
Run Code Online (Sandbox Code Playgroud)

它是确定,或者我应该移动OpenUrlCommandMainViewModel

hel*_*ker 5

实际上你应该在Model中实现该方法,但是在ViewModel中实现该命令.这将与MVVM架构更加一致,在这种情况下,根本不需要额外的工作.

在您的ViewModel中:

class MainViewModel : BaseViewModel
{
    private Model _model;    

    ICommand OpenUrlCommand { get { return new RelayCommand(_model.openUrl); } }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

如果您想从View中"发送"一些URL,您可以使用CommandParameter它,并进行输入RelayCommand.

更新:请注意,由于Command绑定所在的DataTemplate是ItemTemplate,因此您应该在某些实现Command ItemViewModel,而不是在MainViewModel.然后,创建Items一个ObservableCollection<ItemViewModel>而不是ObservableCollection<Model>,并像这样初始化集合:

IEnumerable<Model> models= getSomeModelsToStartWith();
var Items = new ObservableCollection<ItemViewModel>(models.Select(m => new ItemViewModel(m));
Run Code Online (Sandbox Code Playgroud)