WPF C# 访问内部 SelectedItemCollection

WPF C# Access Internal SelectedItemCollection

我正在使用 WPF C# 和 MVVM 方法开发应用程序。 我有一个 ListView(显示文件列表),其中 SelectionMode 设置为扩展;我正在尝试获取所选项目的名称。我在 SelectionChanged 上有一个命令。 SelctionChanged 事件的参数为(对象 xx)。在调试中,我知道 xx 包含我需要的信息,但是,我在尝试从 xx 中提取名称时遇到了很大的困难。 调试告诉我 xx 的类型为 System.Windows.Control.SelectedItemCollection。我无法在我的视图模型代码中将变量设置为这种类型,因为这种类型是 'protected'。我尝试将其设置为键入 FileModel 但没有成功。 我想创建一个 List<string> 的所选项目的名称。非常欢迎任何建议。

从视图中提取:

        <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>

从 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);
         //}
      }

如果您不知道类型以便正确转换,您必须查阅 .NET API 参考资料:单击成员并按“F1”以允许 Visual Studio 在浏览器中打开会员文档。

在这里您将了解到 ListBox.SelectedItemsIList 类型。 在不查阅文档的情况下,我们可以预期 SelectedItemCollection 至少会实现 IEnumerable.

或者,您始终可以检查 object.GetType() 返回的 Type 对象:

Debug.WriteLine(xx.GetType().BaseType);

或者在调试会话期间直接在 Window 中输入 xx.GetType()

在这里你会了解到 SelectedItemCollection 的基类型是 ObservableCollection<object>.

IEnumerable 是使用 foreach.
枚举集合所需的最少类型 然后,您可以将每个单独的项目显式转换为其原始类型或使用 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);
  }
}

感谢 BionicCode,你的解决方案总的来说没有用,它拒绝了这条线 IEnumerable<string> selectedFileModelNames = selectedFileModels.Select(fileModel => fileModel.Name);.

但是,它让我开始寻找解决方案。代码如下:

      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;
         }
      }

它现在可以正常工作,并且简化了我代码的其他部分。