I adapted some code from this answer (https://stackoverflow.com/a/51254960/3797778) in the hopes of adding SelectedValuePath functionality since the collection i want to store is actually a collection of property values contained in a collection of objects that the listbox is actually bound to. So basically i want to bind the selected items to a list of ID's rather than the complete objects.
My adapted code for the ListBox is as follows:
public class MultipleSelectionListBox : ListBox, INotifyPropertyChanged
{
public static readonly DependencyProperty BindableSelectedItemsProperty =
DependencyProperty.Register("BindableSelectedItems",
typeof(IEnumerable<dynamic>), typeof(MultipleSelectionListBox),
new FrameworkPropertyMetadata(default(IEnumerable<dynamic>),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnBindableSelectedItemsChanged));
public event PropertyChangedEventHandler PropertyChanged;
public IEnumerable<dynamic> BindableSelectedItems
{
get => (IEnumerable<dynamic>)GetValue(BindableSelectedItemsProperty);
set {
SetValue(BindableSelectedItemsProperty, value);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("BindableSelectedItems"));
}
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.OnSelectionChanged(e);
BindableSelectedItems = SelectedItems.Cast<dynamic>();
}
private static void OnBindableSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is MultipleSelectionListBox listBox)
{
List<dynamic> newSelection = new List<dynamic>();
if (!string.IsNullOrWhiteSpace(listBox.SelectedValuePath))
foreach (var item in listBox.BindableSelectedItems)
{
var collectionValue = item.GetType().GetProperty(listBox.SelectedValuePath).GetValue(item, null);
foreach (var lbItem in listBox.Items)
{
if (lbItem.GetType().GetProperty(listBox.SelectedValuePath).GetValue(lbItem, null) == collectionValue)
newSelection.Add(lbItem);
}
}
else
newSelection = listBox.BindableSelectedItems as List<dynamic>;
listBox.SetSelectedItems(listBox.BindableSelectedItems);
}
}
}
the rest you can probibly assume but i'll block out the basics anyway.
My objects in the LB:
public class DeviceChannelInfo
{
public DeviceStateInfo parentDeviceState { get; set; }
public string name { get; set; }
public string displayName { get; set; }
public int id { get; set; }
}
My LB code:
<uc:MultipleSelectionListBox ItemsSource="{Binding Source={x:Static local:SharedProperties.deviceChannelInfos}, Mode=OneWay}" SelectionMode="Extended" SelectedValuePath="name" IsSynchronizedWithCurrentItem="True" BindableSelectedItems="{Binding MyCollectionOfSelectedIDs, Mode=TwoWay}">
The binding never seems to communicate with with my 'MyCollectionOfSelectedIDs' prop.