I am developing and App using WPF C# using the MVVM methodology.
I have a ListView
(showing a list of files) with SelectionMode
set to Extended; I am trying to get the names of the selected items. I have a command on SelectionChanged
. The SelctionChanged
event has parameter of (object xx). In Debug I know xx holds the information I need, however, I am having great difficulty trying to extract the names from xx.
The debug tell me xx is of type System.Windows.Control.SelectedItemCollection
. I am unable to set a variable to this type in my view model code since this type is 'protected'. I have tried setting it to type FileModel
without success.
I want to create a List<string>
of the names of the selected items. Any suggestions would be very welcome.
Extract from View:
<ListView x:Name="lvFiles" Grid.Row="4" Grid.Column="2" Margin="20,0,0,0"
SelectionMode="{Binding SelectMode}"
ItemsSource="{Binding SelectedItem.FileItems, ElementName=FolderView}" >
<ie1:Interaction.Triggers >
<ie1:EventTrigger EventName ="SelectionChanged" >
<ie1:InvokeCommandAction CommandParameter="{Binding ElementName=lvFiles, Path=SelectedItems}"
Command="{Binding SelectionChangedCommand}" />
</ie1:EventTrigger>
</ie1:Interaction.Triggers>
Extract from ViewModel:
private void NewSelectedItems(object xx)
{
var zz = xx.ToString();
//List<FileModel> sls = new List<FileModel>();
//SelectedFileList.Clear();
//foreach (var item in (List<FileModel>)xx)
//{
// SelectedFileList.Add(item.Name);
//}
}
CodePudding user response:
If you don't know the type in order to cast it properly, you must consult the .NET API reference: click on the member and press "F1" to allow Visual Studio to open the member documentation in your browser.
Here you would learn that ListBox.SelectedItems
is of type IList
.
Without consulting the documentation, we can expect that SelectedItemCollection
would at least implement IEnumerable
.
Alternatively, you can always inspect the Type
object returned by object.GetType()
:
Debug.WriteLine(xx.GetType().BaseType);
Or simply enter xx.GetType()
into the Immediate Window during the debugging session.
Here you would learn that the base type of SelectedItemCollection
is ObservableCollection<object>
.
IEnumerable
is the least required type to enumerate the collection using foreach
.
You can then cast each individual item explicitly to its original type or use LINQ Enumerable.Cast<T>()
:
private void NewSelectedItems(object selectedItems)
{
IEnumerable<FileModel> selectedFileModels = selectedItems.Cast<FileModel>();
// In case SelectedFileList IS of type List<T>
IEnumerable<string> selectedFileModelNames = selectedFileModels.Select(fileModel => fileModel.Name);
SelectedFileList.AddRange(selectedFileModelNames);
// In case SelectedFileList IS NOT of type List<T>
foreach (FileModel selecteFileModel in selectedFileModels)
{
SelectedFileList.Add(selecteFileModel.Name);
}
}
CodePudding user response:
Thanks BionicCode your solution in total did not work it rejected the line
IEnumerable<string> selectedFileModelNames = selectedFileModels.Select(fileModel => fileModel.Name);
.
However, it got me started on a solution. The code is below:
private void NewSelectedItems(ObservableCollection<Object> selectedItems)
{
IEnumerable<FileViewModel> selectedFileModels = selectedItems.Cast<FileViewModel>();
SelectedFileList.Clear();
SelectedFile = "";
for (int idx = 0; idx < selectedFileModels.Count(); idx )
{
SelectedFileList.Add(selectedFileModels.ElementAt<FileViewModel>(idx).Name);
}
SelectedFiles = string.Join(", ", SelectedFileList.ToArray());
OSDBM.FileNames = SelectedFileList.ToArray();
if (SelectedFileList.Count() == 1)
{
SelectedFile = SelectedFileList[0];
OSDBM.FileName = SelectedFile;
}
}
It's now working as I want and has simplified other parts of my code.