2016-05-26 13 views
1

TasksのリストにバインドされたItemsControlがあります。そしてそのモデルTaskをそのビューTaskViewとviewmodel TaskViewModelに与えたいと思います。WPF/MVVM:ItemsControlのview/viewmodelにモデルをバインドする方法

私はそのようなビューのプロパティに値をバインドしようとしています

<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. これを行うのより慣用な方法はありますか?

    モデル

    namespace Models 
    { 
        public class Task 
        { 
        public string Id { get; set; } 
    
        public Status Status { get; set; } 
    
        // And other properties ... 
        }  
    } 
    

    リスト(親)

    のViewModel

    012:ここで

は重要な部分です

ビュー

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

TaskVi ewModel

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

多分私は使用しているパターンを認識しませんが、MVVMを使って、モデルからビューモデルを作成するのではなく、ビューモデルからviewmodelを作成しないでください。 – grek40

+0

@ grek40それは私によく見えません。 MVVMパターンによれば、モデルはViewModelについての知識を持ってはならず、ViewModelはViewについて知ってはいけません。 MSDNのドキュメントから取得した画像を参照してください。https://i-msdn.sec.s-msft.com/dynimg/IC564167.png – basgys

+1

画像を見て、ビューとモデルの間に直接の接続はありません。モデルはviewmodelについて知らないが、viewmodelはモデルについて知っているので、 'new viewmodel(modelData)'のようなものを言うことは合法です。これは、ビューモデルとビューに似ています。 – grek40

答えて

1

あなたのモデルとビューモデルの部品が正しく定義されている、しかし、あなたは(あなたのモデルに双方向のデータバインディングを有効にする)INotifyPropertyChangedインターフェースを見てしたいことがあります。

ビューモデルは、DataContextプロパティ(Property Value Inheritance参照)を介してユーザーコントロールに自動的に渡されます。これは、継承されたDataContextを上書き(およびTaskViewModelの新しいインスタンスに設定)と同じように

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

あなたは、UserControlで明示的にDataContextを指定してはなりません。

+0

モデルをDataContextとして持つことで、プロパティ(StatusとId)を読み取ることができます。言い換えれば、それは動作します。 しかし、私のViewModelはもうコマンドを受け取りません。私は、ビューとViewModelはもうリンクされていないと思います。 – basgys

+0

ViewModelをViewのDataContextとして、ModelをViewModelの「DataContext」として持つ方が良いのではないでしょうか?またはそのようなもの。 – basgys

+1

その場合、 'Task'を' TaskModel'にリネームし、 'Task'プロパティを持つ' TaskViewModel'クラスを導入する必要があります。 'ObservableCollection 'に 'TaskViewModel'のインスタンスを入れてください。 – Ehssan

関連する問題