Si je définis TreeViewItem Background, il ne met en évidence que l’en-tête. Comment puis-je mettre en évidence toute la ligne?
J’ai trouvé un post presque en train de résoudre un problème
Mais il y a quelques problèmes: 1. Il ne met pas en évidence toute la ligne 2. L’arbre a le style XP sur Vista. Je voudrais que cela ressemble à Vista, mais si l’utilisateur a changé le thème en XP, il devrait être XP. 3. Tant de XAML …
Des idées, que devrais-je chercher?
Nous y voilà, troisième fois un charme. Si vous voulez quelque chose qui ressemble à ceci.
Celui-ci prend un peu plus de travail. Je suis sûr qu’il y a plusieurs façons de procéder, mais cette méthode utilise un convertisseur de longueur et une méthode d’extension TreeViewItem pour obtenir la profondeur. Ces deux éléments sont étroitement liés à l’arborescence visuelle de TreeViewItem, donc si vous commencez à manipuler les modèles, vous risquez d’avoir des problèmes. Encore une fois, voici la partie importante, et ci-dessous le code complet.
Extension TreeViewDepth
public static class TreeViewItemExtensions { public static int GetDepth(this TreeViewItem item) { TreeViewItem parent; while ((parent = GetParent(item)) != null) { return GetDepth(parent) + 1; } return 0; } private static TreeViewItem GetParent(TreeViewItem item) { var parent = VisualTreeHelper.GetParent(item); while (!(parent is TreeViewItem || parent is TreeView)) { parent = VisualTreeHelper.GetParent(parent); } return parent as TreeViewItem; } }
LeftMarginMultiplierConverter
public class LeftMarginMultiplierConverter : IValueConverter { public double Length { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var item = value as TreeViewItem; if (item == null) return new Thickness(0); return new Thickness(Length * item.GetDepth(), 0, 0, 0); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new System.NotImplementedException(); } }
Contrôle
Style complet de TreeViewItem
TreeViewItem Header ne s’étire pas?
Ce problème se produit car le modèle par défaut de WPF pour TreeViewItem
est défini comme une Grid
3 colonnes par 2 lignes. La première ligne est ItemsPresenter
à l’en-tête (en fait une Border
) et la deuxième à l’article ItemsPresenter
. Les deux lignes sont rendues visibles ou masquées si nécessaire, afin de réaliser l’expansion de l’arbre lorsque vous cliquez sur le petit sortingangle – qui occupe la colonne zéro de la Grid
.
Les deux lignes n’ont besoin que d’une colonne supplémentaire. Par exemple, dans la deuxième ligne, nous ne devons rien avoir à col-0, row-1, car cette partie vide doit être en retrait lorsque IsExpanded
a la valeur true. Mais le mystère commence lorsque nous notons que le ItemsPresenter
, basé dans col-1, row-1, spécifie Grid.ColumnSpan=2
.
Malheureusement, dans la ligne supérieure, la Border
Grid.Column=1
l’en-tête est définie sur Grid.Column=1
… mais pas sur ColumnSpan. Puisque le col-2 de la Grid
a la Width=*
cela signifie que l’en-tête / la bordure ne s’étire pas horizontalement.
En d’autres termes, il semble que la conception de la grid à 3 colonnes ne sert à rien, sauf pour empêcher spécifiquement l’étirement de s’étirer. Autant que je sache, un simple arrangement 2×2 serait plus souple [edit: voir la note de bas de page 2] et prend en charge soit le non-étirement complet, soit l’en-tête «déchiqueté», via les mécanismes d’alignement WPF
classiques.
Idéalement, nous changerions la Grid
pour ne plus avoir que 2 colonnes au lieu de 3. Comme ce n’est pas si simple, nous ferons en sorte que l’en-tête ItemsPresenter
2 colonnes , comme le ItemsPresenter
le ItemsPresenter
.
Ok, voici un petit programme de travail complet et autonome (XAML uniquement) qui démontre – et corrige – le problème:
Si vous exécutez ce programme comme indiqué, vous verrez quelque chose comme ceci. Ceci est le comportement corrigé, qui vous permet de reprendre le contrôle complet du comportement d’étirement de l’en-tête TreeViewItem
:
Notez la partie BEGIN / END avec les lignes pointillées dans la source XAML. Fondamentalement, je viens de définir Grid.ColumnSpan=2
sur la Border
incriminée, afin qu’elle remplisse la largeur de la Grid
. Cet élément est émis par le modèle TreeViewItem
. Par conséquent, j’ai trouvé qu’un moyen efficace de modifier ses propriétés était d’utiliser un Style
ciblage dans le dictionnaire de ressources du Style
TreeViewItem
. Oui, confus Ce Style
est accessible via TreeViewItem.ItemContainerStyle
.
Pour voir le comportement cassé (existant), vous pouvez commenter la partie entre les lignes pointillées:
Vous pouvez également définir ces styles dans un dictionnaire de ressources plutôt que d’utiliser la propriété ItemContainerStyle
comme je l’ai fait ici. Je l’ai fait de cette façon car il réduit la scope du correctif, de sorte que Border
contrôles Border
non liés ne soient pas affectés. Si vous avez besoin d’une méthode plus discriminante pour cibler uniquement ce contrôle, vous pouvez tirer parti du fait qu’il possède Name='Bd'
.
[edit:] Cette solution n’utilise pas de reflection! Ne soyez pas effrayé par les données démo insignifiantes – cela n’a rien à voir avec ce problème; c’était le moyen le plus simple de récupérer des données hiérarchiques à des fins de démonstration, tout en gardant le programme entier minuscule.
[edit # 2:] Je me suis juste rendu compte que ce que les concepteurs essayaient d’éviter avec l’arrangement de grid 3×2 était l’effet inesthétique suivant (exagéré ici par une capture d’écran zoomée). Donc, si vous adoptez l’une des solutions de cette page, soyez prévenu que vous pourriez ne pas vouloir cela:
Si vous voulez dire quelque chose comme cette capture d’écran
Largeur totale TreeViewItem http://www.bendewey.com/code/treeViewFullWidth2.png
Mise à jour Comme noté cet exemple a la chute d’être en retrait sur les sous-éléments
Largeur totale TreeViewItem http://www.bendewey.com/code/treeViewFullWidth2a.png
Alors cela devrait vous aider. Son également basé sur http://msdn.microsoft.com/en-us/library/ms788727.aspx vous pouvez changer le gabarit de TreeViewItem à un StackPanel et définir le paramètre ItemsPanel Left Margin à 19. Dans l’arbre, vous définissez le HorizontalContentAlignment = “Étendue”. Je joins la ressource entière ci-dessous, mais voici la partie importante.
Contrôle
Ressources
Si vous voulez dire quelque chose comme cette capture d’écran
LineItem Hightlighting dans un TreeView http://www.bendewey.com/code/treeViewFullWidth.png
Alors cela devrait vous aider. Son basé sur http://msdn.microsoft.com/en-us/library/ms788727.aspx vous pouvez apporter des modifications à la disposition de la grid de TreeViewItem. Fondamentalement, vous supprimez la troisième colonne. Dans le TreeView, vous définissez ensuite HorizontalContentAlignment = “Stretch”. Je joins la ressource entière ci-dessous, mais voici la partie importante.
Contrôle
Ressources
C’est de loin la solution la plus simple. Créez simplement un rectangle, appelez-le Hb, et définissez sa marge à -100px et non visible. Ne le définissez que sur Visible lorsque vous l’avez sélectionné ou sur la souris. C’est un hack, mais vous pouvez utiliser jusqu’à 5 niveaux de TreeViewItems nesteds (100> 19 * 5)
Source du problème lorsque TreeView est utilisé avec ItemsSource, référencé à partir du texte du lien , j’ai modifié du code de la classe TreeViewItemExtensions:
public static class TreeViewItemExtensions { public static int GetDepth(this TreeViewItem item) { while (GetSelectedTreeViewItemParent(item) != null) { var parent = GetSelectedTreeViewItemParent(item); if (parent != null) return parent.GetDepth() + 1; item = parent; } return 0; } public static TreeViewItem GetSelectedTreeViewItemParent(this TreeViewItem item) { DependencyObject parent = VisualTreeHelper.GetParent(item); while (!(parent is TreeViewItem || parent is TreeView)) { parent = VisualTreeHelper.GetParent(parent); } return parent as TreeViewItem; } }
Utilisé quelque chose comme theseven7 pour faciliter l’utilisation du code de bendewey avec des TreeViewItems basés sur des modèles …
public static int GetDepth(this TreeViewItem item) { FrameworkElement elem = item; var parent = VisualTreeHelper.GetParent(item); var count = 0; while (parent != null && !(parent is TreeView)) { var tvi = parent as TreeViewItem; if (parent is TreeViewItem) count++; parent = VisualTreeHelper.GetParent(parent); } return count; }
J’ai réussi cela en copiant le ItemContainerStyle en utilisant blend, en donnant un nom à la grid dans laquelle l’élément est placé, puis en définissant l’arrière-plan de la grid.
Pour une approche basée uniquement sur XAML, j’ai pris l’une des solutions de Bendewey et je l’ai un peu transformée en une solution plus simple:
Le style ci-dessous doit permettre aux éléments Treeview de couvrir:
Pour le faire fonctionner et s’effondrer comme un bon Treeview, les déclencheurs ci-dessous devraient permettre ceci:
Juste imbriquer les déclencheurs dans le modèle de contrôle. Les couleurs / padding / design devront être ajustés pour répondre à vos propres besoins, mais ce qui précède devrait être une idée très simple sur une base XAML uniquement.