WPF / MVVM:如何将模型绑定到ItemsControl中的view / viewmodel

时间:2016-05-26 09:48:54

标签: c# wpf xaml .net-4.5 mvvm-light

我有一个ItemsControl绑定到Tasks列表。我想将该模型Task提供给其视图TaskView和viewmodel TaskViewModel

我尝试在视图属性上绑定值,如:

<views:TaskView Model="{Binding}" />

然后绑定视图和视图模型之间的值:

public partial class TaskView
{
    public TaskView()
    {
        InitializeComponent();

        // Attempt to bind view.IdProperty with viewmodel.Id
        var binding = new Binding("Id");
        SetBinding(IdProperty, binding);
    }

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

然而它不起作用。由于我是C#/ .NET的新手,我不知道我是否正确的方向,因为对于常见问题IMO似乎很复杂。

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

问题:

  1. 如何从数据源构建视图并将模型传递给该视图? (上面解释的问题)
  2. 如何从该模型中读取值到视图? (参见TaskView.xaml)
  3. 有没有更惯用的方法呢?
  4. 以下是关键部分:

    模型

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

    查看

    <ItemsControl x:Name="Tasks"
                    Grid.Row="1"
                    Grid.ColumnSpan="2"
                    ItemsSource="{Binding Path=Tasks, Mode=OneWay}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate DataType="models:Task">
                <!-- TODO : Bind model to task view/viewmodel -->
                <views:TaskView Model="{}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    

    任务(孩子)

    TaskView.xaml.cs

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

    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>
    

    TaskViewModel

    class TaskViewModel : ActionViewModelBase
    {
        public Task Model { get; set; }
        // ...
    }    
    

1 个答案:

答案 0 :(得分:1)

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

视图模型会通过DataContext属性自动传递给您的用户控件(请参阅:Property Value Inheritance)。

<DataTemplate DataType="models:Task">
    <!-- DataContext of TaskView is a single Task -->
    <views:TaskView />
</DataTemplate>

您不能在DataContext中明确指定UserControl,因为这会覆盖继承的DataContext(并将其设置为TaskViewModel的新实例。)< / p>

<UserControl x:Class="TaskView">  
  <!-- DataContext of UserControl is a single Task (inherited) -->
  <Border>
      <Grid Background="{Binding Status, Converter={StaticResource StatusBackgroundColourConverter}}">
          <!-- ... -->
      </Grid>
  </Border>
</UserControl>