J'ai une ObservableCollection
d'objets classés avec un nom et un ensemble de coordonnées 3D. J'ai également une ObservableCollection
de couches, chacune devant contenir une grille 2D.
Configuration du Problème
L'objectif est d'utiliser un ItemsControl
, probablement imbriqué, pour afficher ces objets de la manière suivante : si la coordonnée Z détermine la couche, et les coordonnées X et Y spécifient la position de chaque objet sur la grille, alors l'objet devrait être affiché dans un TabControl
, où le TabItem
correspond à la coordonnée Z et accueille une Grid
où les attributs Grid.Row
et Grid.Column
déterminent où le nom de l'objet est écrit sur le TabItem
.
Important : bien que chaque coordonnée 3D ne soit utilisée qu'une seule fois, un objet "Entry" peut avoir plusieurs coordonnées 3D, et peut donc apparaître plusieurs fois sur une grille et/ou différents TabItems
.
Remarque : le modèle de données n'est pas gravé dans la pierre; si le problème peut être résolu avec un autre modèle de données, je suis ouvert à le changer. Cependant, l'affichage est une exigence du client — il pourrait être modifié, mais j'aurais besoin d'arguments extrêmement convaincants à cet égard.
Informations de Contexte
Les objets ressemblent à ceci (BindableBase
provient de la Prism Library) :
public class Entry : BindableBase {
public string Name { set; get; }
private EntryCoordinates coordinates;
public EntryCoordinates Coordinates {
set { SetProperty(ref coordinates, value); }
get { return coordinates; }
}
}
public class EntryCoordinates : BindableBase {
private int x;
public int X {
set { SetProperty(ref x, value); }
get { return x; }
}
private int y;
public int Y {
set { SetProperty(ref y, value); }
get { return y; }
}
private int z;
public int Z {
set { SetProperty(ref z, value); }
get { return z; }
}
Les objets Entry
sont hébergés dans des "couches d'entrée" :
public class EntryLayer : ObservableCollection {
}
En fin de compte, je veux être capable de modifier les objets Entry
(qui sont en réalité plus complexes) via l'interface utilisateur, donc la liaison de données bidirectionnelle est une nécessité absolue.
Effort Jusqu'à Maintenant
En utilisant l'excellent WPF Grid Extension de @Rachel, j'ai implémenté un ItemsControl
qui peuple une Grid
comme désiré :
<Setter Property="Grid.Row" Value="{Binding Coordinates.X}"/>
<Setter Property="Grid.Column" Value="{Binding Coordinates.Y}"/>
Le GridCellThumb
est un contrôle personnalisé qui permet le glisser-déposer (omis ici pour des raisons de clarté) et expose des propriétés de dépendance de coordonnées :
public class GridCellThumb : Thumb {
public static readonly DependencyProperty XCoordinateProperty = DependencyProperty.Register("XCoordinate", typeof(int), typeof(GridCellThumb));
public int XCoordinate {
get { return (int)GetValue(XCoordinateProperty); }
set { SetValue(XCoordinateProperty, value); }
}
public static readonly DependencyProperty YCoordinateProperty = DependencyProperty.Register("YCoordinate", typeof(int), typeof(GridCellThumb));
public int YCoordinate {
get { return (int)GetValue(YCoordinateProperty); }
set { SetValue(YCoordinateProperty, value); }
}
}
Le TileControl
est un contrôle utilisateur qui affiche le nom d'un Entry
:
Je suis bloqué pour trouver comment envelopper l'ItemsControl
original dans un modèle de TabControl
afin d'atteindre l'objectif d'afficher une entrée, potentiellement plusieurs fois, correctement. Par exemple, la liaison au chemin Coordinates.Z
fonctionne, mais crée autant de TabItems
qu'il y a d'entrées :
<Setter Property="Header"
Value="{Binding Coordinates.Z}" />
<Setter Property="TabIndex"
Value="{Binding Coordinates.Z}" />
J'ai essayé les solutions proposées par @greg40 (ItemsControl imbriqué), @d.moncada (un autre ItemsControl imbriqué), et @Sheridan (remontant dans l'arborescence visuelle), mais j'échoue toujours de manière magistrale lorsqu'il s'agit de relier une Entry
à une EntryLayer
donnée.
Est-ce que quelqu'un a d'autres idées à explorer ? Comme je l'ai dit, je suis également ouvert à restructurer mon modèle de données, si cela conduit à une solution plus facile.
Mise à Jour 2018-01-08
J'ai exploré la possibilité d'utiliser des Buttons
au lieu d'un TabControl
dans le sens de lier leur état cliqué à l'affichage d'informations variables sur la grille. Cependant, cela n'a fait que déplacer le problème et en créer un nouveau : les données ne sont plus pré-chargées, ce qui est crucial pour les exigences du client.
Je considère désormais fortement la possibilité de suggérer un changement des exigences au client et concevoir un tout autre modèle de données. Afin d'éviter de prendre à nouveau une mauvaise direction, j'apprécierais beaucoup s'il y avait quelqu'un dans la communauté avec une opinion forte sur ce problème qu'il serait prêt à partager avec moi.