How to Implement a ListBox of Checkboxes in WPF?
Assuming TopicList
is not an ObservableCollection<T>
therefore when you add items no INotifyCollection
changed is being fired to tell the binding engine to update the value.
Change your TopicList
to an ObservableCollection<T>
which will resolve the current issue. You could also populate the List<T>
ahead of time and then the binding will work via OneWay; however ObservableCollection<T>
is a more robust approach.
EDIT:
Your TopicList
needs to be a property not a member variable; bindings require properties. It does not need to be a DependencyProperty
.
EDIT 2:
Modify your ItemTemplate
as it does not need to be a HierarchicalDataTemplate
<ListBox.ItemTemplate> <DataTemplate> <StackPanel> <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate>
Use ObservableCollection<Topic>
instead of List<Topic>
Edit
it implements INotifyCollectionChanged interface to let WPF know when you add/remove/modify items
Edit 2
Since you set TopicList
in code, it should be a Dependency Property, not a common field
public ObservableCollection<CheckedListItem> TopicList { get { return (ObservableCollection<CheckedListItem>)GetValue(TopicListProperty); } set { SetValue(TopicListProperty, value); } } public static readonly DependencyProperty TopicListProperty = DependencyProperty.Register("TopicList", typeof(ObservableCollection<CheckedListItem>), typeof(MainWindow), new UIPropertyMetadata(null));
Edit 3
To see changes in items
- implement
INotifyPropertyChanged
interface inCheckedListItem
(each setter should callPropertyChanged(this, new PropertyChangedEventArgs(<property name as string>))
event) - or derive
CheckedListItem
fromDependencyObject
, and convertName
,ID
,IsChecked
to dependency properties - or update them totally (
topicList[0] = new CheckedListItem() { Name = ..., ID = ... }
)
First you dont need a HeirarchicalDataTemplate for this. Just regular DataTemplate as Aaron has given is enough.Then you need to instantiate the TopicList ObservableCollection somewhere inside the constructor of the class. which makes the ObservableCollection alive even before you add data in to it And binding system knows the collection. Then when you add each and every Topic/CheckedListItem it will automatically shows up in the UI.
TopicList = new ObservableCollection<CheckedListItem>(); //This should happen only onceprivate void InitializeTopicList( MyDataContext context ){ TopicList.Clear(); foreach ( Topic topic in topicList ) { CheckedListItem item = new CheckedListItem(); item.Name = topic.DisplayName; item.ID = topic.ID; TopicList.Add( item ); }}