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) :
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
?