2

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

DBS
  • 151
  • 2
  • 18
  • The behavior is correct if you select B, A is still selected. Do you need to have last selected, since you can select multiple items? – Rekshino Jul 03 '18 at 08:44
  • Yes , that is right I need the last selected item @Rekshino – DBS Jul 03 '18 at 08:57

1 Answers1

1

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>
Rekshino
  • 6,954
  • 2
  • 19
  • 44
  • Worked! Thanks a lot – DBS Jul 03 '18 at 09:14
  • It is working only when I bind the LastSelected with Mode=TwoWay Is this possible to make it work with OneWay? – DBS Jul 03 '18 at 09:14
  • Mmm I have checked that now, and not fully work... it is raise the SelectedViewVME change, but its will deselect the first item – DBS Jul 03 '18 at 09:16
  • You can bind it with `OneWayToSource`. – Rekshino Jul 03 '18 at 09:20
  • 1
    I can't follow you with deselect. But in this behavior you can use whatever logic(also add LastUnselected) if you evaluate `SelectionChangedEventArgs.RemovedItems` and `SelectionChangedEventArgs.AddedItems` – Rekshino Jul 03 '18 at 09:24