Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 将列表框绑定到ViewModels的ObservableCollection_Wpf_Xaml_Mvvm_Listbox - Fatal编程技术网

Wpf 将列表框绑定到ViewModels的ObservableCollection

Wpf 将列表框绑定到ViewModels的ObservableCollection,wpf,xaml,mvvm,listbox,Wpf,Xaml,Mvvm,Listbox,使用MVVM将列表框的项绑定到ViewModel时是否有约定 在下面的XAML中,我创建了一个按钮列表框。列表框绑定到来自我的ViewModel的可观察集合。然后我想将按钮的Command属性绑定到ICommand。问题是,当我添加该绑定时,我绑定的是数据对象,而不是ViewModel 我是否只是将MyListOfDataObjects属性更改为ViewModels列表?如果是,我在哪里实例化这些新对象?我更喜欢使用依赖项注入,因为它们有几个依赖项。我是否更改GetData lambda 总的来

使用MVVM将列表框的项绑定到ViewModel时是否有约定

在下面的XAML中,我创建了一个按钮列表框。列表框绑定到来自我的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);
            }
        }
    }
}

谢谢。

我想说这取决于你想在哪里使用按键功能。如果它总是与MyData对象相关,那么如果可能,将命令放在MyData对象中会不会太不合适?另外,我不会仅仅因为要向MyData对象ViewModels添加命令属性而调用它们,因为它们与视图没有关联

或者,如果希望在VM中使用该命令,则可以尝试使用窗口的datacontext绑定该命令。例如:

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

尽管我过去在这方面遇到过麻烦,并将命令添加到各个对象中。

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

一个简单的例子是将模型作为XML,并让ViewModel对其进行解析,仅从每个元素中获取一个特定属性(例如名称),然后将它们添加到列表中。视图中将仅显示此列表

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

如果您有一个特定的命令,该命令对特定类型的数据执行特定的操作,您可以将其放在更通用的ViewModel类型中,您可以使用CanExectue仅在特定情况下允许此命令。但是,命令仍应位于ViewModel中


在您的特定情况下,我认为在ViewModel中使用该命令没有问题,并且当提出该命令时,它将对您的数据执行您需要的任何操作。您不需要ViewModels列表,只需要一个。

我绑定的是数据对象,而不是ViewModel,这是什么意思?@Blachshma我的意思是,按下按钮时调用的ButtonPressedCommand将是MyData类中定义的命令,而不是MainViewModel类。这将命令绑定到MainWindow类,不是MainWindowViewModel。更改DataContext.ButtonPressedCommand}的路径可以解决这一问题。我对此考虑得更多了,也许这更像是我在MVVM中展示自己的天赋的一个例子,但我认为目标之一是将尽可能多的UI逻辑排除在数据对象之外。为此,我在一个单独的项目中定义了数据类,该项目由应用程序的其他部分使用。一旦我向这个类添加了命令,那么我需要向WPF添加对项目的引用。由于数据层也被web服务使用,这似乎不自然。@Josh感谢您指出更正。是的,我同意你的看法。如果它是一个只在一个视图中使用的命令,那么将它放在对象中是不好的。我想,如果您绑定到MainWindowViewModel,您将拥有一个包含集合中所有项的switch语句的方法,这也是不需要的。也许您可以专门为继承MyData对象的集合创建一个新对象-这就是您在提到ViewModels列表时提到的吗?我认为您对从MyData继承的对象集合的想法与我一开始的想法类似。同样,我只是假设这个问题会有一个既定的模式。@Josh如果你找到了,请告诉我