Comment mettre en place une zone de liste de Cases à cocher dans WPF?
Bien que peu d'expérience avec l'écriture des applications Winforms, la... "flou" de WPF échappe encore m'en termes de bonnes pratiques et de modèles de conception.
Malgré le remplissage de ma liste au moment de l'exécution, de ma zone de liste apparaît vide.
J'ai suivi les instructions de cet article utile en vain. Je soupçonne que je suis absent quelque sorte de DataBind()
méthode où je raconte la zone de liste que je me suis fait la modification de la liste sous-jacente.
Dans ma MainWindow.xaml, j'ai:
<ListBox ItemsSource="{Binding TopicList}" Height="177" HorizontalAlignment="Left" Margin="15,173,0,0" Name="listTopics" VerticalAlignment="Top" Width="236" Background="#0B000000">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/>
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Dans mon code-behind, j'ai:
private void InitializeTopicList( MyDataContext context )
{
List<Topic> topicList = ( from topic in context.Topics select topic ).ToList();
foreach ( Topic topic in topicList )
{
CheckedListItem item = new CheckedListItem();
item.Name = topic.DisplayName;
item.ID = topic.ID;
TopicList.Add( item );
}
}
Qui, en retraçant à travers, je sais, c'est être rempli avec quatre points.
MODIFIER
J'ai changé TopicList
à un ObservableCollection
. Cela ne fonctionne toujours pas.
public ObservableCollection<CheckedListItem> TopicList;
EDIT #2
J'en ai fait deux changements qui peuvent aider:
Dans le .fichier xaml:
ListBox ItemsSource="{Binding}"
Dans le code source après que j'ai à remplir la liste:
listTopics.DataContext = TopicList;
J'obtiens une liste, mais il n'est pas automatiquement la mise à jour de la case états lorsque j'actualise ces. Je soupçonne un peu plus loin la lecture de ma part résoudre cela.
- Downvoter: exactement comment cette question montrent pas d'effort de recherche, n'est pas clair ou pas utile?
Vous devez vous connecter pour publier un commentaire.
Utilisation
ObservableCollection<Topic>
au lieu deList<Topic>
Modifier
il implémente l'interface INotifyCollectionChanged laisser WPF savoir quand vous ajouter/supprimer/modifier des éléments
Edit 2
Depuis que vous avez établi
TopicList
dans le code, il devrait être une Propriété de Dépendance, pas un champ communModifier 3
À voir des changements dans les éléments
INotifyPropertyChanged
interface dansCheckedListItem
(chaque setter doit appelerPropertyChanged(this, new PropertyChangedEventArgs(<property name as string>))
événement)CheckedListItem
deDependencyObject
, et de convertir de laName
,ID
,IsChecked
pour les propriétés de dépendancetopicList[0] = new CheckedListItem() { Name = ..., ID = ... }
)En supposant
TopicList
n'est pas unObservableCollection<T>
par conséquent, lorsque vous ajoutez des éléments nonINotifyCollection
changé est déclenché à dire le moteur de liaison de mise à jour de la valeur.Changer votre
TopicList
à unObservableCollection<T>
qui permettra de résoudre le problème actuel. Vous pouvez également remplir leList<T>
à l'avance et ensuite la liaison travail via OneWay; cependantObservableCollection<T>
est une approche plus rigoureuse.EDIT:
Votre
TopicList
doit être un bien qui n'est pas une variable de membre; les liaisons nécessitent des propriétés. Il ne pas besoin d'être unDependencyProperty
.EDIT 2:
Modifier votre
ItemTemplate
comme il n'a pas besoin d'être unHierarchicalDataTemplate
IsSelected
bien surListBoxItem
:<CheckBox IsChecked="{Binding IsSelected, Mode=OneWay, RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}}"
Vous devriez également définirIsHitTestVisible
etIsFocusable
à false.D'abord, vous n'avez pas besoin d'un HeirarchicalDataTemplate pour cela. Juste régulière DataTemplate comme Aaron a donné est suffisant.
Ensuite, vous devez instancier la TopicList ObservableCollection quelque part à l'intérieur du constructeur de la classe. ce qui rend l'ObservableCollection en vie, même avant d'ajouter des données dans Et le système de liaison connaît de la collection. Lorsque vous ajoutez ensuite tous les sujets/CheckedListItem il s'affiche automatiquement dans l'INTERFACE utilisateur.
TopicList
dépendance propertiyD'autres ont déjà fait des suggestions utiles (utiliser une collection observable pour obtenir la liste de notification de modification, de faire la collecte d'une propriété plutôt qu'un champ). En voici deux, ils n'ont pas:
1) Chaque fois que vous rencontrez un problème avec la liaison de données, regardez dans la fenêtre de Sortie pour s'assurer que vous êtes de ne pas obtenir de toute erreur de liaison. Vous pouvez passer beaucoup de temps à essayer de résoudre le mauvais problème si vous ne le faites pas.
2) Comprendre le rôle de notification de changement de joue dans la liaison. Des changements dans votre source de données ne peut pas et ne se propage à l'INTERFACE utilisateur, sauf si la source de données met en œuvre le changement de notification. Il y a deux façons de faire cela normal propriétés: vérifiez la source de données dérivent de
DependencyObject
et de faire de la propriété liée à une dépendance de la propriété, ou la source de données mettre en œuvreINotifyPropertyChanged
et augmenter lePropertyChanged
cas lorsque la valeur de la propriété change. Lors de la liaison d'unItemsControl
à une collecte, à l'utilisation d'une collection de classe qui implémenteINotifyCollectionChanged
(commeObservableCollection<T>
), de sorte que des modifications du contenu et de l'ordre de la collection se propage à la limite de contrôle. (Notez que si vous voulez apporter des changements aux éléments dans la collection se propage à l'contrôles liés, ces éléments doivent mettre en œuvre le changement de notification de trop.)changer votre liaison à