C# 命名动态生成的组合框项

C# 命名动态生成的组合框项,c#,wpf,combobox,C#,Wpf,Combobox,我目前正在.NETCore3.1中从事一个WPF项目。在执行过程中,我必须将一些文件名读取到组合框中。我首先将它们添加到列表中。之后,我遍历该列表并将它们添加到组合框中 问题 因为它们只有在选择了另一个组合框中的项目时才可以访问,所以我需要禁用刚才添加的项目。因此,为了以后启用它们,我需要命名它们。但我不知道我们该怎么做 这是我的密码: 在foreach(ComboBoxItem currentItems in comboAircrafter.Items)行中,我得到一个异常: System.I

我目前正在.NETCore3.1中从事一个WPF项目。在执行过程中,我必须将一些文件名读取到组合框中。我首先将它们添加到列表中。之后,我遍历该列表并将它们添加到组合框中

问题 因为它们只有在选择了另一个组合框中的项目时才可以访问,所以我需要禁用刚才添加的项目。因此,为了以后启用它们,我需要命名它们。但我不知道我们该怎么做

这是我的密码:

在foreach(ComboBoxItem currentItems in comboAircrafter.Items)行中,我得到一个异常:

System.InvalidCastException:“无法将类型为“System.String”的对象强制转换为类型为“System.Windows.Controls.ComboBoxItem”。

我真的没什么主意了。我在谷歌上搜索了一整天,但什么也没找到


祝大家今天愉快

您正在尝试将
字符串
转换为
ComboBoxItem
。用数据填充组合框时,添加的是
字符串
,而不是
组合框项
。因此,您应该在最后一个
foreach
循环中使用
String

foreach (string currentComboItems in comboAircraft.Items)
{
    currentComboItems.Name = "comboAircraftItems" + currentComboItems;
}
另一种解决方案是将
ComboBoxItem
添加到组合框中,而不是
String

foreach (string currentListItem in aircraft)
{
    ComboBoxItem item = new ComboBoxItem()
    {
        Content = currentListItem,
        Name = "comboAircraftItems" + currentListItem
    };
    comboAircraft.Items.Add(item);
}

您正在尝试将
字符串
转换为
ComboBoxItem
。用数据填充组合框时,添加的是
字符串
,而不是
组合框项
。因此,您应该在最后一个
foreach
循环中使用
String

foreach (string currentComboItems in comboAircraft.Items)
{
    currentComboItems.Name = "comboAircraftItems" + currentComboItems;
}
另一种解决方案是将
ComboBoxItem
添加到组合框中,而不是
String

foreach (string currentListItem in aircraft)
{
    ComboBoxItem item = new ComboBoxItem()
    {
        Content = currentListItem,
        Name = "comboAircraftItems" + currentListItem
    };
    comboAircraft.Items.Add(item);
}

@t-kldw,当直接使用UI元素时,您的任务很难解决。 但是,如果您将数据和它们的表示分离,解决这个问题非常简单,因为MVVM中应该这样做

不幸的是,对于一个完整实现的示例,您所写的内容包含的细节很少。 我只能给出部分建议。 有必要为一个组合框中所需的数据创建一个额外的容器类。 此类必须具有INotifyPropertyChanged实现

要简化,请从主题中获取实现

为了让我能给出进一步的建议,你需要提供你任务的更多细节。 例如,我甚至不知道为什么需要currentComboItems.Name。。。。
我认为您显然做错了什么。

@t-kldw,当直接使用UI元素时,您的任务很难解决。 但是,如果您将数据和它们的表示分离,解决这个问题非常简单,因为MVVM中应该这样做

不幸的是,对于一个完整实现的示例,您所写的内容包含的细节很少。 我只能给出部分建议。 有必要为一个组合框中所需的数据创建一个额外的容器类。 此类必须具有INotifyPropertyChanged实现

要简化,请从主题中获取实现

为了让我能给出进一步的建议,你需要提供你任务的更多细节。 例如,我甚至不知道为什么需要currentComboItems.Name。。。。
我认为您显然做错了什么。

ItemsControl.Items
只保存数据对象。为了呈现这些项目,每个项目都被包装到一个容器中,例如,
ComboBoxItem
。这些UI容器由与当前
ItemsControl
关联的
itemsContainerGenerator
生成。
ItemContainerGenerator
还负责跟踪数据项与其UI容器之间的映射。
要获取项目的容器,请使用
ItemsControl.ItemContainerGenerator

DependencyObject itemContainer = ItemContainerGenerator.ContainerFromItem(item);
您的简化代码变成:

List<string> allAircrafts = Directory.EnumerateFiles(
    Path.Combine(
      Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
      @"\ApplicationName\Aircraft\"),
    "*.lxml",
    SearchOption.TopDirectoryOnly)
  .Select(Path.GetFileNameWithoutExtension)
  .ToList();

comboAircraft.ItemsSource = allAircrafts;

foreach (string item in allAircrafts)
{
  var itemContainer = comboAircraft.ItemContainerGenerator.ContainerFromItem(item) as ComboBoxItem;
  itemContainer.Name = "comboAircraftItems" + itemContainer.Content;
}
List allairrafts=Directory.enumerate文件(
路径。联合收割机(
GetFolderPath(Environment.SpecialFolder.ApplicationData),
@“\ApplicationName\Aircrafter\”,
“*.lxml”,
SearchOption.TopDirectoryOnly)
.Select(Path.GetFileNameWithoutExtension)
.ToList();
comboAircraft.ItemsSource=所有飞机;
foreach(allAircrafts中的字符串项)
{
var itemContainer=ComboAircrafter.ItemContainerGenerator.ContainerFromItem(item)作为ComboBoxItem;
itemContainer.Name=“comboAircraftItems”+itemContainer.Content;
}
但请注意,您选择的方法存在问题。当为
itemscpntrol
启用UI虚拟化时,只有可见的项才会生成其容器。滚动查看器视口外的项目不会生成,并且不能由
ItemContainerGenerator
返回
由于默认情况下,
组合框
未启用UI虚拟化,因此只要不启用此性能优化功能,此功能仍可工作

最佳解决方案需要您为显示过滤项的组合框创建一个过滤源集合。这样,您就不会在控件中添加用户不感兴趣且无论如何都无法选择的项

创建一个类型为
ObservableCollection
的集合,其中包含您命名的
组合框的主要
所选项目

将此集合设置为第二个筛选的组合框的
项源

或者,创建原始源集合的
CollectionViewSource
,并将其绑定到辅助
组合框
<代码>ICollectionView
支持筛选。 正确的解决方案


使用这两种推荐的解决方案中的任何一种都不需要关心物品容器。这增加了灵活性并简化了代码。

ItemsControl。Items
仅保存数据对象。为了呈现这些项目,每个项目都被包装到一个容器中,例如,
ComboBoxItem
。这些UI容器由
ItemContainerGenerator
生成,如下所示
List<string> allAircrafts = Directory.EnumerateFiles(
    Path.Combine(
      Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
      @"\ApplicationName\Aircraft\"),
    "*.lxml",
    SearchOption.TopDirectoryOnly)
  .Select(Path.GetFileNameWithoutExtension)
  .ToList();

comboAircraft.ItemsSource = allAircrafts;

foreach (string item in allAircrafts)
{
  var itemContainer = comboAircraft.ItemContainerGenerator.ContainerFromItem(item) as ComboBoxItem;
  itemContainer.Name = "comboAircraftItems" + itemContainer.Content;
}