Home > front end >  WPF C# Access Internal SelectedItemCollection
WPF C# Access Internal SelectedItemCollection

Time:01-26

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.

  •  Tags:  
  • Related