Je souhaite répertorier une ItemsCollection, mais au lieu de rendre les éléments de la collection, je souhaite rendre les sous-objets atteints via une propriété de l'élément de collection. Pour être plus précis: ce sera une visionneuse de carte 2D pour un jeu (bien que dans son état actuel ce n'est pas encore 2D). Je catalogue une ItemsControl à une ObservableCollection <Square>, où Square a une propriété appelée Terrain (de type Terrain). Le terrain est une classe de base et a plusieurs descendants.Sélection de DataTemplate en fonction du type de sous-objet
Ce que je veux, c'est que ItemsControl rende la propriété Terrain de chaque élément de collection, pas l'élément de collection lui-même.
Je peux déjà faire ce travail, mais avec un surcoût inutile. Je veux savoir s'il y a un bon moyen de supprimer les frais inutiles.
Ce que je actuellement sont les classes suivantes (simplifié):
public class Terrain {}
public class Dirt : Terrain {}
public class SteelPlate : Terrain {}
public class Square
{
public Square(Terrain terrain)
{
Terrain = terrain;
}
public Terrain Terrain { get; private set; }
// additional properties not relevant here
}
Et un UserControl appelé MapView, contenant les éléments suivants:
<UserControl.Resources>
<DataTemplate DataType="{x:Type TerrainDataModels:Square}">
<ContentControl Content="{Binding Path=Terrain}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type TerrainDataModels:Dirt}">
<Canvas Width="40" Height="40" Background="Tan"/>
</DataTemplate>
<DataTemplate DataType="{x:Type TerrainDataModels:SteelPlate}">
<Canvas Width="40" Height="40" Background="Silver"/>
</DataTemplate>
</UserControl.Resources>
<ItemsControl ItemsSource="{Binding}"/>
Donné ce code, si je fais:
mapView.DataContext = new ObservableCollection<Square> {
new Square(new Dirt()),
new Square(new SteelPlate())
};
Je reçois quelque chose qui ressemble exactement à ce que j'attends: un StackPanel contenant un bronzage boîte (pour la saleté) et une boîte en argent (pour le SteelPlate). Mais je l'obtiens avec des frais généraux inutiles.
Ma préoccupation particulière est mon DataTemplate pour la place:
<DataTemplate DataType="{x:Type TerrainDataModels:Square}">
<ContentControl Content="{Binding Path=Terrain}"/>
</DataTemplate>
Ce que je veux vraiment dire est « non, ne prend pas la peine de rendre la place elle-même, rendre sa propriété Terrain à la place ». Cela se rapproche de cela, mais cela ajoute deux contrôles supplémentaires à l'arborescence visuelle pour chaque Square: un ContentControl, tel que codé explicitement dans le XAML ci-dessus, et son ContentPresenter. Je ne veux pas particulièrement un ContentControl ici; Je veux vraiment court-circuiter et insérer le DataTemplate de la propriété Terrain directement dans l'arbre de contrôle. Mais comment puis-je dire à ItemsControl de rendre collectionitem.Terrain (en recherchant ainsi l'un des DataTemplates ci-dessus pour l'objet Terrain) plutôt que de rendre collectionitem (et de chercher un DataTemplate pour l'objet Square)? Je veux utiliser des DataTemplates pour les terrains, mais pas du tout pour le Square - c'était juste la première approche que j'ai trouvée qui fonctionnait correctement. En fait, ce que je veux vraiment faire est quelque chose de complètement différent - je veux vraiment définir DisplayMemberPath de ItemsControl sur "Terrain". Cela rend le bon objet (l'objet Dirt ou SteelPlate) directement, sans ajouter ContentControl ou ContentPresenter supplémentaire. Malheureusement, DisplayMemberPath restitue toujours une chaîne, en ignorant les DataTemplates pour les terrains. Donc ça a la bonne idée, mais c'est inutile pour moi.
Tout cela peut être une optimisation prématurée, et s'il n'y a pas facile façon d'obtenir ce que je veux, je vais vivre avec ce que j'ai. Mais s'il y a une "méthode WPF" que je ne sais pas encore sur le point de lier à une propriété au lieu de l'ensemble de la collection, cela va ajouter à ma compréhension de WPF, qui est vraiment ce que je cherche.
J'ai ajouté une deuxième réponse. Jetez un coup d'oeil et laissez-moi savoir si cela aide. – bendewey