DBS
DBS

Reputation: 151

WPF ListBox multiple selection not raise SelectedItem on model

I have a problem with my ListBox I've set the ListBox selection mode to Multiple The problem is that the Selected Item fire only once, and when I select other items, it is doesn't change the SelectedItem at the view model. I'm sure its selection them because I bind a property to true when they are selected, but the selected item does not update. For example: Lets say I have ListBox with the following: A B C Choose A -> the ViewModel update the selectedItem to A Choose B -> The ViewModel doesn't update the SelectedItem but I can see that B is selected When I deselect A, the ViewModel update the SelectedItem to null Someone already faced that issue? My main goal is to keep my SelectedItem update to the one I chose He is my code for the View:

<ListBox HorizontalAlignment="Center"  ItemsSource="{Binding AvailableDagrVMEs}"
                     SelectedItem="{Binding SelectedDagrVME}"
                     SelectionMode="Multiple"
                     VirtualizingStackPanel.IsVirtualizing="False"
                     ScrollViewer.HorizontalScrollBarVisibility="Auto" Padding="0" Margin="0" ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.PanningMode="HorizontalOnly"
                     Background="Transparent"
                     BorderThickness="0">
                    <ListBox.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Rows="1"/>
                        </ItemsPanelTemplate>
                    </ListBox.ItemsPanel>
                    <ListBox.ItemContainerStyle>
                        <Style TargetType="{x:Type ListBoxItem}">
                            <Setter Property="IsSelected" Value="{Binding Taken, Mode=TwoWay}"/>
                        </Style>
                    </ListBox.ItemContainerStyle>
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <DockPanel>
                                <Image Source="{Binding Icon , Converter={StaticResource BitmapToImageSourceConverter}}"/>
                            </DockPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

And ViewModel:

        public BaseVME SelectedDagrVME
    {
        get { return selectedDagrVME; }
        set
        {
            if (selectedDagrVME != value)
            {
                Set("SelectedDagrVME", ref selectedDagrVME, value);
            }
        }
    }

I've tried: TwoWay binding/UpdateTriggerSource

Upvotes: 2

Views: 2439

Answers (1)

Rekshino
Rekshino

Reputation: 7325

Since you have Multiple selection, the SelectedItem will always be the first selected in your selection. To get the last selected Item you have to register for SelectionChanged event and access SelectedItems property, which contains all items from your selection. You can implement it with a behavior for you could reuse it.

Behavior:

public class ListBoxSelection : Behavior<ListBox>
{
    public static readonly DependencyProperty LastSelectedProperty = DependencyProperty.Register(nameof(LastSelected), typeof(object), typeof(ListBoxSelection), new PropertyMetadata(default(object)));

    public object LastSelected
    {
        get
        {
            return (object)GetValue(LastSelectedProperty);
        }
        set
        {
            SetValue(LastSelectedProperty, value);
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
    }

    private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
//you can also use whatever logic if you evaluate e.RemovedItems and e.AddedItems
        if ((AssociatedObject?.SelectedItems?.Count??0)>0)
        {
            LastSelected = AssociatedObject.SelectedItems[AssociatedObject.SelectedItems.Count-1];
        }
        else
        {
            LastSelected = null;
        }

    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
    }
}


XAML:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:b="clr-namespace:NameSpaceWhereBahaviorDefined"

<ListBox ...>
    <i:Interaction.Behaviors>
        <b:ListBoxSelection LastSelected = "{Binding VMSelection}" />
    </i:Interaction.Behaviors>
</ListBox>

Upvotes: 1

Related Questions