Binding CommandParameter to the SelectedItems of a custom control?

mshwfmshwf EGMember ✭✭✭

I'm creating a custom control, that has -among other properties- Command, CommandProperty and SelectedItems of type object that might be a merely object or an ObservableCollection<object> depending on other property IsMultiSelect.

Here is the control on android emulator (it has 4 items in its ItemsSource property) :

enter image description here

Now I need to bind the CommandParameter to SelectedItems:

<controls:TogglesRow x:Name="TogRow"
                     ItemsSource="{Binding Items}" DisplayMemberPath="Name"
                     Command="{Binding ItemSelectedCommand}" 
                     CommandParameter="{Binding Source={x:Reference TogRow}, 
                     Path=SelectedItems}"/>

But the problem is that it takes the previous SelectedItems, meaning that in the first time I select an Item, the CommandParameter is null, the next time will take the first selected item...etc.

The btn is the tapped button (custom button), which is initialized in the propertyChanged delegate of the UI properties (ItemsSourceProperty, DisplayMemberPathProperty.. etc)):

btn.SelectionChanged += (s, e) =>
            {
                if (IsMultiSelect)
                {
                    if (btn.IsSelected)
                        (SelectedItems as ObservableCollection<object>).Add(item);
                    else
                        (SelectedItems as ObservableCollection<object>).Remove(item);
                }
                else
                {
                    var allToggleButtons = stackContainer.Children.Where(x => x is ToggleButton);
                    allToggleButtons?.ForEach(x => ((ToggleButton)x).IsSelected = false);
                    btn.IsSelected = true;
                    SelectedItems = item;
                }
                if (!IsMultiSelect && btn.IsSelected)
                    SelectedItemsChanged?.Invoke(this, new TogglesRowSelectionChangedEventArgs
                    {
                        SelectedItems = SelectedItems,
                        SelectedIndices = ItemsSource.IndexOf(item)
                    });
                else if (IsMultiSelect)
                {
                    SelectedItemsChanged?.Invoke(this, new TogglesRowSelectionChangedEventArgs
                    {
                        SelectedItems = SelectedItems,
                        SelectedIndices = (SelectedItems as ObservableCollection<object>).Select(x => ItemsSource.IndexOf(x))
                    });
                }
                Command?.Execute(CommandParameter);

            };

Bindable properties:

public static readonly BindableProperty CommandProperty =
            BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(TogglesRow), null);

        public ICommand Command
        {
            get { return (ICommand)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }

        public static readonly BindableProperty CommandParameterProperty =
            BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(TogglesRow), null);

        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        public static readonly BindableProperty SelectedItemsProperty = BindableProperty.Create(nameof(SelectedItems), typeof(object), typeof(TogglesRow),
            defaultBindingMode: BindingMode.TwoWay);
        public object SelectedItems
        {
            get { return GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

I know that this is logical, but any way around it, to late-bind the CommandParameter property. For example, re-evaluate the binding expression to get the latest SelectedItems?

Answers

Sign In or Register to comment.