0

I hope I can find some help here.I'm using telerik and got a RadComboBox with MultiSelection. I've extended the functionality of RadComboBox by using an attached property called "SelectItemsHelper" and add the desired items to the SelectedItems collection of the ComboBox. But when i try to get the selected items i dont get any Values. What do i do wrong?

My SelectedItemsHelper

using System.Collections;
using System.Windows;
using Telerik.Windows.Controls;

namespace WpfAutoQuery
{
    public class SelectedItemsHelper
    {
    
        public static readonly DependencyProperty SelectedItemsProperty =
        DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(SelectedItemsHelper), new FrameworkPropertyMetadata((IList)null, new PropertyChangedCallback(OnSelectedItemsChanged)));
          
        public static IList GetSelectedItems(DependencyObject d)
        {
            return (IList)d.GetValue(SelectedItemsProperty);
        }

        public static void SetSelectedItems(DependencyObject d, IList value)
        {
            d.SetValue(SelectedItemsProperty, value);
        }

        private static void OnSelectedItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var comboBox = sender as RadComboBox;
            if (comboBox != null)
            {                
                IList selectedItems = GetSelectedItems(comboBox);
                if(selectedItems != null)
                {
                      comboBox.SelectedItems.Clear();
                      foreach (var item in selectedItems)
                      {
                          comboBox.SelectedItems.Add(item);
                      }
                }
            }                               
        }
     }
}

My RadComboBox in View

<telerik:RadComboBox Name="rcbSection" Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2" Margin="10" IsEditable="False"
                     ItemsSource="{Binding Sections}" DisplayMemberPath="Line1" AllowMultipleSelection="True"  
                     local:SelectedItemsHelper.SelectedItems="{Binding SelectedSections}">                                              
</telerik:RadComboBox>

My SelectedSections property in ViewModel

public ObservableCollection<Section> SelectedSections
        {
            get { return GetPropertyValue<ObservableCollection<Section>>(); }
            set { SetPropertyValue(value); }
        }

Section Class

 public class Section : INotifyPropertyChanged
    {
        public Section(string line1)
        {
            this.Line1 = line1;                
        }
        
        public string Line1
        {
            get { return GetPropertyValue<string>(); }
            set { SetPropertyValue(value); }
        }

I made a Screenshot while debuging enter image description here

Desaad91
  • 1
  • 1
  • Callback is called when attached property value is changed. As a matter of fact callback will not be called if you just add/remove items to `ObservableCollection`, only assigning a completely new instance of `ObservableCollection` will. Not sure if `SetPropertyValue` rise `PropertyChanged` either, make sure it does. You didn't show the part which add something to `SelectedSections`, an easy *fix* will be to set `SelectedSections = null` after adding items and then back (rising `PropertyChanged` after each step of course). – Sinatr May 05 '21 at 10:14
  • @Sinatr Thank for your answer. Well does this what you described not already happen in OnSelectedItemsChanged in the SelectedItemsHelper? – Desaad91 May 05 '21 at 11:45
  • Is the breakpoint on screenshot hit upon launch (first time) right? I expect at this moment the observable collection is simply empty. Later, when you add items, the breakpoint doesn't occurs, right? – Sinatr May 05 '21 at 11:49
  • @Sinatr Yes you're right. It get's hit there the first time. What i dont get is why does the "GetSelectedItems" dont get any items out of the var combobox. As you can see in the Screenshot the var combobox has 9 values and also contains the SelectionBoxItems. So why does it not pass it to the IList selectedItems? – Desaad91 May 05 '21 at 11:57
  • I am not sure what are you trying to do there right now, but `ComboBox` items have *nothing* to do with attached property value. You are binding property `SelectedSections` to attached property and that's all. How many items combobox has it doesn't matter. `SelectedSections` is empty. I assume you handle selection in viewmodel or code behind and then *set* the new value for `SelectedSections` and *only then* it will be available in callback. – Sinatr May 05 '21 at 12:03

1 Answers1

0

I have found a solution. But also only thanks to Stackoverflow. I found a similar question to my topic and there has a user answered the question with a solution in great detail. However, I do not quite understand why it works now. Maybe someone could explain me the difference or what exactly happens?

What i changed so far:

ViewModel

private ObservableCollection<Section> _selectedSections = new ObservableCollection<Section>();
public ObservableCollection<Section> SelectedSections
{
    get { return _selectedSections; }
} 

var selectedSectionList = _selectedSections;

SelectedItemsHelper

private static void OnSelectedItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var comboBox = sender as RadComboBox;
        IList coll = e.NewValue as IList;

        if (coll is INotifyCollectionChanged)
        {
            (coll as INotifyCollectionChanged)
                .CollectionChanged += (s, e3) =>
                {
                    if (null != e3.OldItems)
                        foreach (var item in e3.OldItems)
                            comboBox.SelectedItems.Remove(item);
                    if (null != e3.NewItems)
                        foreach (var item in e3.NewItems)
                            comboBox.SelectedItems.Add(item);
                };
        }
        if (null != coll)
        {
            if (coll.Count > 0)
            {
                comboBox.SelectedItems.Clear();
                foreach (var item in coll)
                    comboBox.SelectedItems.Add(item);
            }

            comboBox.SelectionChanged += (s, e2) =>
            {
                if (null != e2.RemovedItems)
                    foreach (var item in e2.RemovedItems)
                        coll.Remove(item);
                if (null != e2.AddedItems)
                    foreach (var item in e2.AddedItems)
                        coll.Add(item);
            };
        }
Desaad91
  • 1
  • 1