I've made a CheckedListbox in xaml using this code:
<ListBox Height="340" ItemsSource="{Binding Sections}" SelectedItem="{Binding SelectedSection}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And its bind to this collection:
public ObservableCollection<CheckedListItem<String>> Sections { get; set; }
private CheckedListItem<String> _selectedSection;
public CheckedListItem<String> SelectedSection
{
get { return _selectedSection; }
set
{
_selectedSection = value;
RaisePropertyChanged("SelectedSection");
}
}
The CheckedListItem class looks like this:
public class CheckedListItem<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool isChecked;
private T item;
public CheckedListItem()
{ }
public CheckedListItem(T item, bool isChecked = false)
{
this.item = item;
this.isChecked = isChecked;
}
public T Item
{
get { return item; }
set
{
item = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item"));
}
}
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
}
}
}
I tried to set a breakpoint in the _selectedSection = value; part of the code but it never gets triggered when i select/deselect an item in the CheckedListBox.
My question is how can I get the selected item every time its selected/deselected ?
Thanks
Change your XAML
to
<ListBox Height="340" ItemsSource="{Binding Sections}" SelectedItem="{Binding SelectedSection}">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBoxItem IsSelected="{Binding IsChecked}">
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item}" />
</ListBoxItem>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You are probably clicking on the actual textblock
control inside the checkbox
or the square
control which doesn't trigger selectionchanged
for a listbox
. If you try to click outside the bounds of the rectangle say the whitespace
then it will fire.
It'll be more work if you just want the checkbox
as the datatemplate since you want to select/deselect listboxitem
' based on the checkbox
IsChecked property. So just wrap it inside a ListBoxItem
and you should be good to go.
My solution (based on Suplanus and lll solutions above):
<ListBox ItemsSource="{Binding Checkboxes}" SelectionMode="Multiple">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Checked, Mode=TwoWay}" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Checked, Mode=TwoWay}" Content="{Binding Label}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I set ListBoxItem IsSelected property througt style (because standard lll's way not work well)! In this case, when CheckBox is checked ListBoxItem is selected and vice versa. SelectionMode in this case also works well. You can add SelectedItem (or similar property) in Single SelectionMode
<!-- xaml -->
SelectedItem="{Binding SelectedCheckbox}" SelectionMode="Single"
// cs
public CheckboxData SelectedCheckbox { get; set; }
or maybe even better, work directly with ItemsSource (Checkboxes collection in this case) in behind code (your ViewModel for example).
Behind code (for example):
public partial class MainWindow : Window
{
public class CheckboxData
{
public int Id { get; set; }
public string Label { get; set; }
public bool Checked { get; set; }
}
public MainWindow()
{
DataContext = this;
for (int i = 0; i < 50; i++)
Checkboxes.Add(new CheckboxData { Id = i, Label = $"Checkbox {i}" });
}
public IList<CheckboxData> Checkboxes { get; set; } = new List<CheckboxData>();
}
Note:
If you want change Checkboxes collection (or selected item) from behind code (and reflect changes in UI) you have to implement INotifyPropertyChanged and notify when collection (or selected item) has been changed (literally, when object has been re created).
I think the better solution is to not declare in a ListboxItem, because the selection on Hover is shown on the Checkbox.
<ListBox ItemsSource="{Binding Customers}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item.Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With