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.SelectedItems
是 IList
类型。
在不查阅文档的情况下,我们可以预期 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;
}
}
它现在可以正常工作,并且简化了我代码的其他部分。
我正在使用 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.SelectedItems
是 IList
类型。
在不查阅文档的情况下,我们可以预期 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;
}
}
它现在可以正常工作,并且简化了我代码的其他部分。