Okay so I have created a simple MVVM pattern based solution.
My ViewModel
public class MainWindowViewModel : INotifyPropertyChanged
{
public IList SelectedList
{
get { return _selectedList; }
set
{
_selectedList = value;
}
}
private IList _selectedList;
private List<StringValues> _bindStuffList;
private object _lock = new object();
public IEnumerable<StringValues> BindStuffList
{
get { return _bindStuffList; }
}
public MainWindowViewModel()
{
_bindStuffList = new List<StringValues>();
BindingOperations.EnableCollectionSynchronization(_bindStuffList, _lock);
BuildStuff();
}
private async void BuildStuff()
{
await Task.Run(() =>
{
for (int i = 0; i < 15; i++)
{
_bindStuffList.Add(new StringValues { ID = "Item " + i });
}
});
RaisePropertyChanged("BindStuffList");
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
var pc = PropertyChanged;
if (pc != null)
pc(this, new PropertyChangedEventArgs(propertyName));
}
}
The StringValues
is a simple class
public class StringValues
{
public string ID { get; set; }
public bool IsChecked { get; set; }
}
Instead of using the classic ListBox
I have used a custom one
public class CustomListBox : ListBox
{
public CustomListBox()
{
this.SelectionChanged += CustomListBox_SelectionChanged;
}
void CustomListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
public IList SelectedItemsList
{
get { return (IList)GetValue(SelectedItemsListProperty); }
set { SetValue(SelectedItemsListProperty, value); }
}
public static readonly DependencyProperty SelectedItemsListProperty =
DependencyProperty.Register("SelectedItemsList", typeof(IList), typeof(CustomListBox));
}
I Simply used this one in the View
<Window x:Class="StackOverflow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom ="clr-namespace:StackOverflow"
Title="MainWindow" Height="350" Width="525">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<StackPanel>
<custom:CustomListBox ItemsSource="{Binding BindStuffList}"
SelectedItem="{Binding SelectedStuff, Mode=TwoWay}"
SelectionMode="Multiple" SelectedItemsList="{Binding SelectedList,Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding ID}" Margin="2"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsChecked}"/>
</Style>
</ListBox.ItemContainerStyle>
</custom:CustomListBox>
</StackPanel>
</ScrollViewer>
</Window>
The SelectedList
will always hold all the values selected from the UI. If you want you can get rid of the CheckBox
in the DataTemplate
as it is reduntant.