将ListBox绑定到ViewModel的ObservableCollection

时间:2013-01-01 23:15:55

标签: wpf xaml mvvm listbox

使用MVVM将ListBox的项绑定到ViewModel时是否存在约定?

在下面的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 ViewModel:

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

感谢。

2 个答案:

答案 0 :(得分:0)

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

或者,如果您想要VM中的命令,那么您可以尝试使用窗口的datacontext绑定命令。即类似的东西;

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

虽然我过去遇到了麻烦,但又将命令添加到各个对象中。

答案 1 :(得分:0)

在MVVM中,原始数据(也称为Model)与ViewModel之间存在明显的分离。在将数据传递给View之前,ViewModel负责解析数据甚至将其修改为任何形式。

一个简单的例子是将Model作为XML并让ViewModel解析它,只从每个元素中获取特定属性(例如&#34; Name&#34;)并将它们添加到名单。只有此列表才会显示在视图中。

那就是说,我想你可以看到我要去的地方 - 命令应该在Model中的ViewModel 而不是 中。正如您自己所说,您应该尽可能多地保留VM和模型中的UI逻辑。

如果您有一个特定的命令可以对特定类型的数据执行某些特定的操作,那么您可以将它放在更多&#34; general&#34;在ViewModel类型中,您可以使用CanExectue仅在特定情况下允许此命令。但是,该命令仍应位于ViewModel中。

在您的特定情况下,我在ViewModel中看不到有关该命令的问题,并且在引发时它会对您的数据执行任何操作。您不需要ViewModel列表,只需要一个。

相关问题