I need to implement CheckBoxList control with ItemsSource and CheckedItems properties. Items from ItemsSource should be displayed as checked checkboxes if CheckedItems contains these values or unchecked otherwise. Also I need two-way databinding support for CheckedItems property (value of this property should be updated when user clicks on checkboxes).
Here some code which probably can help to understand my problem
XAML:
<UserControl x:Class="Namespace.Controls.CheckBoxList" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ListBox x:Name="LayoutRoot">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>
Code behind:
public partial class CheckBoxList : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CheckBoxList), null);
public static readonly DependencyProperty CheckedItemsProperty = DependencyProperty.Register("CheckedItems", typeof(IEnumerable), typeof(CheckBoxList), null);
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public IEnumerable CheckedItems
{
get { return (IEnumerable)GetValue(CheckedItemsProperty); }
set { SetValue(CheckedItemsProperty, value); }
}
public CheckBoxList()
{
InitializeComponent();
LayoutRoot.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("ItemsSource") { Source = this });
}
}
I think that I need to bind ListBox to UserControl with custom converter, which will return collection of items with additional IsChecked property, but it works only in case of one-way data binding.
Looks like I need two-way binding to two properties at one time, but I don’t know how to implement it and will appreciate any help with this issue.
Thanks in advance.
First of all you should consider deriving from ListBox rather than
UserControl. The ListBox already does most of what you want.Secondly consider one way binding to an IList. You can then add and remove entires to that IList as the respective items are selected.
Rather than try to bind a CheckBox control in an Item Template you make a copy of the ListBox styles, place them in Generic.xaml as the style of your new control. Then modify the unselected and selected visual states using a checked and unchecked check box as part of the visual appearance.
Now you can attach to the SelectionChanged event and use the Event args AddedItems list to add to the bound IList and the RemovedItems list to remove items from the bound list.
You would need to clear and re-add the set of items to the list box SelectedItems list when either your CheckedItems is assigned or the ItemsSource is changed.
There are probably a number gotchas that you will need to work round but this seems like a more direct path to your goal than starting from scratch with a UserControl base.