ComboBox ItemTemplate 在删除所选项目时触发 TargetException?

ComboBox ItemTemplate triggering TargetException when selected item is removed?

我有一个使用 MEF 和 MVVMLight 的 WPF 应用程序 (.NET 4.5)。有一个名为 "DeviceSupervisor" 的共享 MEF 导出,它包含自定义 class、DeviceConfiguration 的 ObservableCollection,它只不过是一些字符串属性。

在主应用程序中,您可以添加和删除设备 to/from 这个 collection。这些模块之一在 ComboBox 中显示设备列表以供选择。

显式条件:

  1. 通过主应用程序
  2. 将一些项目添加到collection
  3. Select 模块下拉列表中的一项
  4. 通过主应用程序从 collection 中删除恰好被选中的项目

将用户更改同步到 DeviceSupervisor 的代码:

foreach (DeviceComplete set in Devices)
{
    set.Configuration.CommunicationDetails = set.Device.Value.CommunicationDetails;
    if (DeviceSupervisor.AvailableDevices.Any(d => d.ID == set.Configuration.ID))
    {
        DeviceSupervisor.AvailableDevices
            .Single(d => d.ID == set.Configuration.ID)
            .CommunicationDetails = set.Configuration.CommunicationDetails;
    }
    else
    {
        DeviceSupervisor.AvailableDevices.Add(set.Configuration);
    }
}

var missing = new HashSet<DeviceConfiguration>(DeviceSupervisor.AvailableDevices
        .Except(Devices.Select(d => d.Configuration)));
foreach (DeviceConfiguration toRemove in missing)
{
    // --- TargetException thrown here ---
    DeviceSupervisor.AvailableDevices.Remove(toRemove);
}

模块上 XAML 中的 CollectionViewSource:

<CollectionViewSource x:Key="AvailableDevicesCvs"
        Source="{Binding Path=AvailableDevices, Mode=OneWay}" Filter="AvailableDevicesCVS_Filter">
</CollectionViewSource>

组合框:

<ComboBox HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top" Width="120"
        ItemsSource="{Binding Source={StaticResource AvailableDevicesCvs}}"
        SelectedItem="{Binding Path=SelectedDevice}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=CommunicationDetails}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

异常:

An unhandled exception of type 'System.Reflection.TargetException' occurred in mscorlib.dll Additional information: Object does not match target type.

堆栈跟踪几乎是所有变灰的 WindowsBase 和 PresentationFramework 引用。 Intellitrace 仅显示我在上面评论的行中抛出的异常。

我的发现/其他笔记

请注意,如果 ComboBox 选择了另一个项目而不是删除的项目,则不会抛出此异常。在任何地方抛出显式 one-way 绑定都没有影响。在我可以在 CollectionChanged 或 Filter 事件中抛出的任何断点之前抛出异常。

经过大量的努力、重组和反复试验,我发现如果我简单地从组合框中删除 ItemTemplate,那么一切都会按预期工作 - 没有例外,并且 ComboBox 会调整选择以弥补缺失物品。

我很紧张,因为我陷入了一些狭隘的视野陷阱,看不到我犯的愚蠢错误 - 但更紧张的是其他原因。

此后我将问题追溯到 CommunicationDetails 属性。 class 的源文件库没有对 MVVMLight 的引用,作为快速获取 xyzChanged 的​​快捷方式(用于其他用途),我编写了 属性,如下所示:

private string mCommunicationDetails;
public string CommunicationDetails
{
    get
    {
        return mCommunicationDetails;
    }
    set
    {
        bool changed = (mCommunicationDetails != value);
        mCommunicationDetails = value;
        if (changed)
        {
            CommunicationDetailsChanged.Raise(this, EventArgs.Empty);
        }
    }
}
public event EventHandler CommunicationDetailsChanged;

将其替换为原版 {get;set;} 属性 有效。我已经用 MVVMLight 属性

替换了它

新建

private string mCommunicationDetails;
public string CommunicationDetails
{
    get
    {
        return mCommunicationDetails;
    }
    set
    {
        if (Set(() => CommunicationDetails, ref mCommunicationDetails, value))
        {
            CommunicationDetailsChanged.Raise(this, EventArgs.Empty);
        }
    }
}
public event EventHandler CommunicationDetailsChanged;

而且有效。

如果有人愿意花时间查找或解释此错误的真正根源,我会接受它作为答案,但我现在接受它以关闭问题。