2017-01-04 7 views
2

MVVMパターンを使用すると、Modelオブジェクトが複雑になるとき、つまりプリミティブではない/組み込まれていないプロパティが含まれているときに問題が発生します。私の特定のインスタンスでは、私自身がModelCオブジェクトのコレクションが含まれていModelBオブジェクトのコレクションが含まれていModelAを持っている:私は複雑なモデルを持つMVVM

class ModelA 
{ 
    public string Name { get; set; } 
    public OberservableCollection<ModelB> Bs { get; set; } 
} 

class ModelB 
{ 
    public string Make { get; set; } 
    public ObservableCollection<ModelC> Cs { get; set; } 
} 

class ModelC 
{ 
    public string Brand{ get; set; } 
} 

ModelB Bsプロパティのコレクションへのアクセスを許可するModelAViewModel。この例では、ModelBのためにViewModelを作成していません。私は、各エンティティはつまり、ModelBModelC、これは物事のMVVMの方法ではないとということを知らされている

<DataTemplate x:Key="modelATemplate"> 
    <Grid Margin="5"> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"> 
      <ItemsControl ItemsSource="{Binding Bs}" ItemTemplate="{StaticResource modelBTemplate}"/> 
     </ScrollViewer> 
    </Grid> 
</DataTemplate> 

<DataTemplate x:Key="modelBTemplate"> 
    <Grid Margin="5" HorizontalAlignment="Center"> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <TextBlock Grid.Row="0" Text="{Binding Make}"> 
     <ItemsControl Grid.Row="1" ItemsSource="{Binding Mode=OneWay, Path=Cs}" 
        ItemTemplate="{StaticResource ResourceKey=modelCTemplate}"> 
     </ItemsControl> 
    </Grid> 
</DataTemplate> 

:私はDataTemplate Sを使用してModelBModelCコレクション(および個々のインスタンス)をスタイリングしています独自のViewModelが必要です。私はModelのクラスを維持するように言われましたが、それらのためにViewModelを作成します。私はこれがどのように機能するかを視覚化することができません。

私が作成した場合ModelBViewModel

public class ModelBViewModel 
{ 
    ModelB MyModelB { get; set; } 
} 

私は苦境を持っている - 私はすでにModelAクラス内ModelBインスタンスを持って、私は今ModelBViewModel内の他のModelBのインスタンスを持っているでしょう。元のModelBコレクションをModelA内に繰り返し、MyModelBプロパティをModelAと一致するように設定して、ModelBViewModelを作成する必要がありますか?むしろ単純なものには少し複雑に思えますか?

+0

あなたのモデルは 'ObservableCollection'(通知を上昇する)を使用しているが、あなたは、例えばのためにあらゆる種類の通知を実装していませんでした'ModelB.Make'、' ModelB.Cs'、 'ModelC.Brand'が変更されます。したがって、技術的にはMVVMではありません。通常、モデルはViewModel( 'INotifyPropertyChanged'が良い)に通知するメカニズムを提供する必要がありますが、ViewModelは' INotifyPropertyChanged'をほぼ実装する必要があります。おそらく 'ModelB' /' ModelC'に 'INotifyPropertyChanged'を実装するほうが簡単ですが、実際にはバインディングに直接使用できるViewModelになります。 – Sinatr

+0

なぜ、 'INotifyPropertyChanged'を実装していないものへのバインディングが動作しているのかを見てください(http://stackoverflow.com/q/7767218/1997232)。 TLDR;モデルに加えられた変更は、ビュー自体が作成された場合にのみビューに表示されます。 – Sinatr

+0

@Sinatr通知を発行しても、「MVVMではない」という意味ではありません。 – jannagy02

答えて

1

MVVMは、 "Model View ViewModel"を意味します。ご覧のように、名前にはModelとViewModelが含まれています。あなたが持っているすべてのModelクラスに専用のViewModelクラスを持たせることです。

ViewModelにはビュー固有のプロパティとロジックが含まれ、Modelクラスにはビジネスモデル固有のプロパティとロジックが含まれている必要があります。

And:はい、いくつかの非常に単純なMVVMの例では、オーバーヘッドになる可能性があります。しかし、ビュー論理がビジネスロジックから分岐し始めるとすぐに、この分離が役立ちます。

元のプロパティを反復処理する必要がある場合は、次のようにします。はい! 私は通常、このようにそれを実行します。

public class ModelBViewModel 
{ 
    private ModelB _model; 

    public ObservableCollection<ModelCViewModel> CVms { get; set; } 

    public ModelBViewModel(ModelB model) { 
     _model = model; 
     CVms = new ObservableCollection(); 
     foreach(var modelC in model.Cs) { 
      CVms.Add(new ModelCViewModel(modelC)); 
     } 
    } 
} 
+1

Linq: 'CVms = new ObservableCollection(model.Cs.Select(c => new ModelCViewModel(c))); –

+0

私は常に各モデルではなく各ビューに対してViewModelを作成する必要があると思っていました。そうでなければ、MVC – zahir

+0

のほかに何が良いのですかはい、ビューごとにビューモデルを作成する必要があります。ただし、複数のビューでモデルデータを表示する場合は、各モデルのビューモデルがあるときに、ビューモデルコードを再利用することが容易になります。 – makzr

関連する問題