2013-01-01 37 views
1

的一个ObservableCollection是否有约定?绑定列表框的ViewModels

在下面的XAML中,我创建了一个ListBox的按钮。 ListBox绑定到我的ViewModel的可观察集合。然后我想将按钮的Command属性绑定到一个ICommand。问题是,当我添加绑定时,我绑定了数据对象,而不是ViewModel。

难道我只是改变MyListOfDataObjects属性为的ViewModels的名单?如果是这样,我在哪里实例化这些新对象?我宁愿使用依赖注入,因为它们会有几个依赖关系。我是否更改GetData lambda?

一般来说:这里认为什么是好的做法?我无法找到任何这种情况的例子,但我认为这很常见。

我使用MVVMLight框架,但我愿意看任何其他框架。

<Window x:Class="KeyMaster.MainWindow" 
     DataContext="{Binding Main, Source={StaticResource Locator}}"> 

    <Window.Resources> 
     <ResourceDictionary> 
      <DataTemplate x:Key="MyDataTemplate"> 
       <Button Command="{Binding ButtonPressedCommand}" 
         CommandParameter="{Binding .}" 
         Content="{Binding Name}" /> 
      </DataTemplate> 
     </ResourceDictionary> 
    </Window.Resources> 

    <Grid x:Name="LayoutRoot"> 
     <ListBox ItemsSource="{Binding MyListOfDataObjects}" 
       ItemTemplate="{StaticResource MyDataTemplate}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal" 
           IsItemsHost="True" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ListBox> 
    </Grid> 
</Window> 

我使用标准MVVMLight视图模型:

using GalaSoft.MvvmLight; 
using KeyMaster.Model; 
using System.Collections.ObjectModel; 

namespace KeyMaster.ViewModel 
{ 
    public class MainViewModel : ViewModelBase 
    { 
     private readonly IDataService _dataService; 
     private ObservableCollection<MyData> _myListOfDataObjects; 

     public MainViewModel(IDataService dataService) 
     { 
      _dataService = dataService; 
      _dataService.GetData(
       (item, error) => 
       { 
        if (error != null) 
        { 
         return; 
        } 

        MyListOfDataObjects = new ObservableCollection<MyData>(item); 
       }); 
     } 

     public ObservableCollection<MyData> MyListOfDataObjects 
     { 
      get { return _myListOfDataObjects; } 
      set 
      { 
       if (_myListOfDataObjects == value) return; 

       _myListOfDataObjects = value; 
       RaisePropertyChanged(() => MyListOfDataObjects); 
      } 
     } 
    } 
} 

感谢。

+0

你是什么意思*“我绑定数据对象,而不是ViewModel”*? – Blachshma

+0

@Blachshma我的意思是按下按钮时调用的ButtonPressedCommand将是MyData类中定义的ButtonPressedCommand,而不是MainViewModel类中定义的。 – Josh

回答

0

在MVVM,存在的原始数据(也被称为模型)和视图模型之间的明确分工。 ViewModel负责解析数据,甚至在将其传递给View之前,将其修改为任何想要的形式。

一个简单的例子是将Model作为XML并使ViewModel解析它,从每个元素中只取一个特定的属性(例如“Name”)并将它们添加到列表中。只有该列表将显示在视图中。

这么说,我想你可以看到我要去哪里 - 命令应该是在视图模型在模型中。正如你自己所说的那样,你应该尽可能多地从虚拟机和模型中取出UI逻辑。

如果您有特定的命令对特定类型的数据执行某些特定的操作,则可以将其更改为“常规”类型的ViewModel,您可以使用CanExectue仅在特定情况下允许使用此命令。但是,该命令应该位于ViewModel中。

在您的具体情况,我没有看到在视图模型具有命令的问题,并提出时,它会做什么,你需要在你的数据。你不需要ViewModel的列表,你只需要一个。

0

我会说它会取决于你想要的按钮的功能。如果它始终与MyData对象相关,那么(如果可能的话)将命令放在MyData对象中会不合适? (ps。我不会仅仅因为你添加一个命令属性给你的MyData对象ViewModels,因为它们没有与视图关联)

或者,如果你想在虚拟机中的命令,那么你可以尝试使用窗口的datacontext绑定命令。即类似的东西;

<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ButtonPressedCommand}" 
        CommandParameter="{Binding .}" 
        Content="{Binding Name}" /> 

尽管我过去遇到过麻烦,并且随着将命令添加到单个对象中去了。

+0

这将命令绑定到MainWindow类,而不是MainWindowViewModel。更改路径到DataContext.ButtonPressedCommand}修复了这个问题。 – Josh

+0

我已经考虑过这一点了,也许这更像是我在MVVM中表现出我的天真的一个实例,但我认为其中的一个目标是保持数据对象中的UI逻辑尽可能多。为此,我在一个由应用程序的其他部分使用的独立项目中定义了数据类。一旦我添加命令到这个类,那么我需要添加一个对WPF项目的引用。由于数据层也被Web服务使用,这看起来不自然。 – Josh

+0

@Josh谢谢你指出更正。我同意你的意见。如果它是一个只在一个视图中使用的命令,那么将它放入对象中并不会很好。我想如果你绑定到MainWindowViewModel,你将会在那里有一个方法,它包含你的集合中所有项目的switch语句,这也不是我们想要的。也许你可以专门为那个继承MyData对象的集合创建一个新的对象 - 当你提到一个ViewModel列表时,你所指的是什么? – Steve