C# WPF/MVVM:如何从ItemsControl将模型绑定到view/viewmodel

C# WPF/MVVM:如何从ItemsControl将模型绑定到view/viewmodel,c#,wpf,xaml,.net-4.5,mvvm-light,C#,Wpf,Xaml,.net 4.5,Mvvm Light,我有一个ItemsControl绑定到任务列表。我想把模型Task赋予它的视图TaskView和viewmodelTaskViewModel <UserControl x:Class="TaskView"> <!-- DataContext of UserControl is a single Task (inherited) --> <Border> <Grid Background="{Binding Status, Conv

我有一个ItemsControl绑定到
任务列表
。我想把模型
Task
赋予它的视图
TaskView
和viewmodel
TaskViewModel

<UserControl x:Class="TaskView">  
  <!-- DataContext of UserControl is a single Task (inherited) -->
  <Border>
      <Grid Background="{Binding Status, Converter={StaticResource StatusBackgroundColourConverter}}">
          <!-- ... -->
      </Grid>
  </Border>
</UserControl>
我尝试在view属性上绑定如下值:

<views:TaskView Model="{Binding}" />
但是,它不起作用。由于我是C#/.NET的新手,我不知道我的方向是否正确,因为对于一个常见的问题来说,这似乎很复杂

请注意,它正确地呈现了任务列表,因此ItemsControl按预期工作

问题:

  • 如何从数据源构建视图并将模型传递给该视图?(上文解释的问题)
  • 如何将该模型中的值读取到视图中?(请参阅TaskView.xaml)
  • 有没有更惯用的方法

  • 以下是关键部分:

    型号

    namespace Models
    {
      public class Task
      {
        public string Id { get; set; }
    
        public Status Status { get; set; }
    
        // And other properties ...
      }    
    }
    
    列表(父项)

    视图模型

    public class ListViewModel : ActionViewModelBase
    {
        public ObservableCollection<Task> Tasks { get; set; }
    }
    
    TaskView.xaml

    <UserControl>
      <UserControl.DataContext>
        <viewModels.TaskViewModel />
      </UserControl.DataContext>
    
      <Border>
          <!-- TODO : Read model attributes -->
          <Grid Background="{Binding Path=Model.Status, Converter={StaticResource StatusBackgroundColourConverter}}">
              <!-- ... -->
          </Grid>
      </Border>
    </UserControl>
    

    您的模型和视图模型零件定义正确,但是您可能需要查看
    INotifyPropertyChanged
    界面(以启用对模型的双向数据绑定)

    视图模型通过
    DataContext
    属性自动传递给用户控件(请参见:)


    也许我不知道你正在使用的模式,但是说到MVVM,你不应该从模型中创建viewmodel,从viewmodel中创建视图,而不是让视图处理模型吗?@grek40这在我看来不正确。根据MVVM模式,模型不应该知道ViewModel,ViewModel也不应该知道View。查看MSDN文档中的图片查看图片并意识到,视图和模型之间没有直接联系。诚然,模型不知道viewmodel,但是:viewmodel知道模型,所以说像
    新建viewmodel(modelData)
    这样的话是合法的。它与viewmodel和view类似。@grek40我同意,但它似乎与您的第一条评论相矛盾,或者我误解了您。通过将模型作为DataContext,我可以读取属性(状态和Id)。换句话说,它是有效的。但是,我的ViewModel不再接收命令。我猜视图和ViewModel不再链接了。取而代之,将ViewModel作为视图的DataContext,将模型作为ViewModel的“DataContext”不是更好吗?在这种情况下,您需要将
    任务
    重命名为
    任务模型
    ,并引入一个具有
    任务
    属性的类
    任务视图模型
    。然后将
    TaskViewModel
    的实例放在
    ObservableCollection
    中。这将是完整的MVVM方法,然后您可以将命令放在
    TaskViewModel
    类中。这很有效!简单明了,正是我喜欢的方式!:)虽然有人告诉我,我们不应该像那样实例化ViewModels,但就我个人而言,我对这个解决方案非常满意。
    public partial class TaskView
    {
        public TaskView()
        {
            InitializeComponent();
        }
    
        public Task Model
        {
            get { return GetValue(ModelProperty) as Task; }
            set { SetValue(ModelProperty, value); }
        }
        public static readonly DependencyProperty ModelProperty =
          DependencyProperty.Register("Model", typeof(Task), typeof(TaskView));
    }  
    
    <UserControl>
      <UserControl.DataContext>
        <viewModels.TaskViewModel />
      </UserControl.DataContext>
    
      <Border>
          <!-- TODO : Read model attributes -->
          <Grid Background="{Binding Path=Model.Status, Converter={StaticResource StatusBackgroundColourConverter}}">
              <!-- ... -->
          </Grid>
      </Border>
    </UserControl>
    
    class TaskViewModel : ActionViewModelBase
    {
        public Task Model { get; set; }
        // ...
    }    
    
    <DataTemplate DataType="models:Task">
        <!-- DataContext of TaskView is a single Task -->
        <views:TaskView />
    </DataTemplate>
    
    <UserControl x:Class="TaskView">  
      <!-- DataContext of UserControl is a single Task (inherited) -->
      <Border>
          <Grid Background="{Binding Status, Converter={StaticResource StatusBackgroundColourConverter}}">
              <!-- ... -->
          </Grid>
      </Border>
    </UserControl>