Using ArcGIS Pro SDK 2.6, I am trying to create a ListBox where the user could select more than 1 item (holding shift / Ctrl key + click)
I can create the listbox and handle the {ItemSource Binding} (for updating the list) and the {SelectedItem Binding} for handling the case of having one item clicked on, using RelayCommand().
How do I configure the Pane ListBox item to allow for multi-line selection?
thank you
To enable multiple selections the shift/control modifiers, we just need to set SelectionMode="Extended" in the properties of the ListBox control in the associated XAML file.
See Microsoft reference: https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.listbox?view=net-5.0#remarks
Cheers,
James
thank you @Anonymous User
Now next question : How do I get the list of selected items in my ICommand RelayCommand() function?
Is there a special {binding} required? (ex: Binding SelectedItem array?)
Severity Code Description Project File Line Suppression State
Error XDG0013 The property "SelectedItems" does not have an accessible setter.
You can bind the UI with isselected property in xaml
<ListBox ItemsSource="{Binding Items}" SelectionMode="Extended">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
So as in above example, in your model , there should be property call IsSelected as boolean type.
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
this.NotifyPropertyChanged();
}
}
And from you relay command, you can access selected item by
Items.Where(i => i.IsSelected);
There is no SelectedItems property in listbox control but you can extend it to enable it.
Below is the custom listbox control class example, you can bind with IList collection type. (any object list you can use)
But I would recommend you to use isselected property approach because It is more straight forward.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace ThanExtendControlLibrary.ExtendedControls
{
public class CustomListBox : ListBox
{
public CustomListBox()
{
this.SelectionChanged += CustomListbox_SelectionChanged;
}
private void CustomListbox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.SelectedItemsList = this.SelectedItems;
}
#region SelectedItemsList
public IList SelectedItemsList
{
get { return (IList)GetValue(SelectedItemsListProperty); }
set { SetValue(SelectedItemsListProperty, value); }
}
public static readonly DependencyProperty SelectedItemsListProperty =
DependencyProperty.Register("SelectedItemsList", typeof(IList), typeof(CustomListBox), new PropertyMetadata(null));
#endregion
}
}
As in above extended control you can use it from your dockpane with
Add xmlns:local="clr-namespace: ThanExtendControlLibrary.ExtendedControls;assembly=[your assemblyname]:
<local:CustomListBox ItemsSource="{Binding Items}" SelectionMode="Extended"
SelectedItemsList="{Binding Path=SelectedList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</local:CustomListBox>
<!-- Note: Declare SelectedList as IList in the model -->
That error you're seeing XDG0013 The property "SelectedItems" does not have an accessible setter. is a result of the fact that unlike the SelectedItem property, the SelectedItems property is read-only.
The simplest approach I can I think of would be to handle the SelectionChanged event of the ListBox in the codebehind to execute a command in the view model, and pass the selected items from the event handler to the command.
Using the DockpaneSimple project as an example, this would involve the following changes-
BookmarkDockpaneViewModel.cs
// added to #region Private Properties
private ICommand _retrieveSelectedBookmarksCommand;
// added to #region Public Properties
public ICommand RetrieveSelectedBookmarksCommand => _retrieveSelectedBookmarksCommand;
// addded to BookmarkDockpaneViewModel() constructor
_retrieveSelectedBookmarksCommand = new RelayCommand((selectedBookmarks) => RetrieveSelectedBookmarks(selectedBookmarks), () => true);
//added to #region Private Helpers
private void RetrieveSelectedBookmarks(object param)
{
System.Collections.IList selectedItems = (System.Collections.IList)param;
Debug.WriteLine(selectedItems.Count);
}
BookmarkDockpane.xaml.cs
//added to public partial class BookmarkDockpaneView : UserControl
private void lstBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listSelectedItems = ((ListBox)sender).SelectedItems;
var vm = (BookmarkDockpaneViewModel)this.DataContext;
vm.RetrieveSelectedBookmarksCommand.Execute(listSelectedItems);
}
BookmarkDockpane.xaml
<ListBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Name="LstBookmarks" SelectionMode="Extended"
ItemsSource="{Binding ListOfBookmarks}" Margin="5"
DisplayMemberPath="Name" SelectionChanged ="lstBox_OnSelectionChanged"
BorderBrush="{DynamicResource Esri_BorderBrush}" BorderThickness="2"
ItemContainerStyle="{DynamicResource Esri_ListBoxItemHighlightBrush}"/>
You can look at this sample: arcgis-pro-sdk-community-samples/Framework/RemoveAddins at master · Esri/arcgis-pro-sdk-community-sa...