C# MVVM模型中的命令是一种糟糕的做法吗?

C# MVVM模型中的命令是一种糟糕的做法吗?,c#,wpf,mvvm,mvvm-light,C#,Wpf,Mvvm,Mvvm Light,我想知道,在MVVM中,将命令放入模型是一种糟糕的做法吗。例如,我有一个带有图像和按钮的列表框。当我点击按钮时,我需要在浏览器中打开url。因此,我的代码如下所示: <ListBox ItemSource="{Binding Items"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <Image Sour

我想知道,在MVVM中,将命令放入模型是一种糟糕的做法吗。例如,我有一个带有图像和按钮的列表框。当我点击按钮时,我需要在浏览器中打开url。因此,我的代码如下所示:

<ListBox ItemSource="{Binding Items">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source={Binding ImageSource} />
                <Button Content="Open url" Command={Binding OpenUrlCommand}"/>
            </StackPanel>
        </DataTemplate>
    </Listbox.ItemTemplate>
</ListBox>
IEnumerable<Model> models= getSomeModelsToStartWith();
var Items = new ObservableCollection<ItemViewModel>(models.Select(m => new ItemViewModel(m));

是否可以,或者我应该将OpenUrlCommand移动到MainViewModel?

您实际上应该在模型中实现该方法,但在ViewModel中实现该命令。这将更加符合MVVM体系结构,在这种情况下,对您来说根本没有额外的工作

在ViewModel中:

class MainViewModel:BaseViewModel
{
    public ObservableCollection<Model> Items {get;set;}
}
class MainViewModel : BaseViewModel
{
    private Model _model;    

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

    // ...
}
如果要从视图发送一些URL,可以使用CommandParameter,并使用类型化的RelayCommand

更新: 注意,由于命令绑定所在的DataTemplate是ItemTemplate,因此应该在某些ItemViewModel中实现该命令,而不是在MainViewModel中。然后,将项目设置为ObservableCollection而不是ObservableCollection,并按如下方式初始化集合:

<ListBox ItemSource="{Binding Items">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source={Binding ImageSource} />
                <Button Content="Open url" Command={Binding OpenUrlCommand}"/>
            </StackPanel>
        </DataTemplate>
    </Listbox.ItemTemplate>
</ListBox>
IEnumerable<Model> models= getSomeModelsToStartWith();
var Items = new ObservableCollection<ItemViewModel>(models.Select(m => new ItemViewModel(m));

实际上,您应该在模型中实现该方法,但在ViewModel中实现该命令。这将更加符合MVVM体系结构,在这种情况下,对您来说根本没有额外的工作

在ViewModel中:

class MainViewModel:BaseViewModel
{
    public ObservableCollection<Model> Items {get;set;}
}
class MainViewModel : BaseViewModel
{
    private Model _model;    

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

    // ...
}
如果要从视图发送一些URL,可以使用CommandParameter,并使用类型化的RelayCommand

更新: 注意,由于命令绑定所在的DataTemplate是ItemTemplate,因此应该在某些ItemViewModel中实现该命令,而不是在MainViewModel中。然后,将项目设置为ObservableCollection而不是ObservableCollection,并按如下方式初始化集合:

<ListBox ItemSource="{Binding Items">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Image Source={Binding ImageSource} />
                <Button Content="Open url" Command={Binding OpenUrlCommand}"/>
            </StackPanel>
        </DataTemplate>
    </Listbox.ItemTemplate>
</ListBox>
IEnumerable<Model> models= getSomeModelsToStartWith();
var Items = new ObservableCollection<ItemViewModel>(models.Select(m => new ItemViewModel(m));

@每个ViewModel都应该有对某个模型的引用,通常以字段的形式,通过构造函数或setter注入。但要点是:ViewModel包含命令;命令将操作委托给模型,无论是模型还是列表中的项目。_model字段只是一个示例。@ASh在ItemTemplate中放置绑定时,命令会自动绑定到项本身,通常是某种ItemViewModel。这意味着它实际上应该在ItemViewModel中实现,而不是在MainViewModel中。@ASh每个ViewModel都应该有对某个模型的引用,通常以字段的形式,通过构造函数或setter注入。但要点是:ViewModel包含命令;命令将操作委托给模型,无论是模型还是列表中的项目。_model字段只是一个示例。@ASh在ItemTemplate中放置绑定时,命令会自动绑定到项本身,通常是某种ItemViewModel。这意味着它实际上应该在ItemViewModel中实现,而不是在MainViewModel中实现。这样做的原因是什么?我只是想知道在ViewModel或Model中应该在哪里使用OpenUrlCommand。这样做的原因是什么?我只是想知道在ViewModel或Model中应该在哪里使用OpenUrlCommand