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

时间:2015-01-19 19:21:14

标签: c# wpf xaml mvvm-light mef

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

在主应用中,您可以在此集合中添加和删除设备。其中一个模块显示ComboBox中的设备列表以供选择。

明确条件:

  1. 通过主应用程序
  2. 添加了许多项目
  3. 从模块下拉列表中选择其中一项
  4. 通过主应用程序
  5. 删除恰好从集合中选择的项目

    将用户更改同步到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>
    

    例外:

      

    未处理的类型&#39; System.Reflection.TargetException&#39;发生在mscorlib.dll中   附加信息:对象与目标类型不匹配。

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

    我的调查结果/其他注释

    请注意,如果ComboBox选择了另一个项目,则不会抛出此异常。在任何地方抛出明确的单向绑定都没有任何影响。在我可以在CollectionChanged或Filter事件中抛出的任何断点之前抛出异常。

    经过大量的挣扎,重组和反复试验后,我发现如果我只是从组合框中删除ItemTemplate,那么一切都按预期工作 - 没有例外,ComboBox会调整选择以补偿丢失的项目。

    我感到紧张,因为我陷入了某个隧道视觉陷阱中,无法看到我犯下的愚蠢错误 - 但更为紧张的是其他东西。

1 个答案:

答案 0 :(得分:0)

我已将问题追溯到CommunicationDetails属性。具有该类源文件的库没有对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;

用vanilla {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;

它有效。

如果有人愿意花时间去寻找或解释这个错误的真正来源,我会接受这个作为答案,但我现在接受这个来解决这个问题。