I have Pack
entity which is displayed on Shelf
user control:
namespace Storage.Model
{
class Pack
{
public string Name { get; set; }
}
}
<UserControl x:Class="Storage.View.Shelf" ... >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Path=Name}"/>
<TextBlock Grid.Row="1" Text="{Binding Path=Capability}"/>
<ItemsControl Grid.Row="2" ItemsSource="{Binding Path=Packs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<TextBlock Text="{Binding Name}" /> // It's okey ???
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
// DataContext for Shelf
namespace Storage.ViewModel
{
public class ShelfViewModel
{
public string Name { get; set; }
public string Capability { get; set; }
public ObservableCollection<Pack> Packs { get; set; }
}
}
With MVVM model it's okay that in DataTemplate
I have binding {Binding Name}
, because if so: IT'S NOT TRUE THAT VIEW SHOULDN'T KNOW ABOUT MODEL CLASS.
It depends on how you define a "model". A model may for example be a reference to a service or business layer. Or it might be an entity object.
It is perfectly fine for the view to bind directly to a property of an entity object that that is exposed through a public property of a view model provided that you actually have access to the entity type and that don't need to modify the definition of it in any way.
Let's for example say that Pack
is a domain type that contains proprietary business logic and is used in several different places accross your business. You might not want to expose such as class to a client application at all. You would typically have some kind of business layer and then a service layer on top of this, that connects to the business layer and returns simple data transfer objects (DTOs) rather than the actual business entities that contains logic.
You can easily bind to such a DTO object directly as long as you don't need it to do something special like for example providing change notifications to the UI. The you will need to write a wrapper (view model) class that exposes the underlying data but also adds the change notification functionality.
So if Pack
is a simple public type that contains everything you need, then you could use it directly. This doesn't break any rule. It if's something else, then use a client specific, or view-aware, wrapper class.
It's programming, so the answer is always "it depends".
If your model has all data in the format that the View needs and the model is immutable, then why not be pragmatic and directly bind the Model to the View?
But as soon as you need a command, write-access to the model properties, data convertion inbetween model and view or if the model properties can change (and you don't want to implement INotifyPropertyChanged on your model) then you shoud wrap a ViewModel arround your model to adress this issues.