通过远程桌面连接时出现 IValueConverter 的 NullReferenceException

NullReferenceException with IValueConverter when connecting via remote desktop

这是一个奇怪的错误。我将枚举绑定到组合框并显示描述属性。我正在使用 WPF Binding a ListBox to an enum, displaying the Description Attribute 的解决方案。所以我的 XAML 的相关部分是:

<Window.Resources>
    <local:EnumConverter x:Key="EnumConverter"/>
    <ObjectDataProvider MethodName="GetValues"
            ObjectType="{x:Type local:MyEnum}"
            x:Key="MyEnumValues">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="local:MyEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>
<ComboBox Name="MyComboBox" ItemsSource="{Binding Source={StaticResource MyEnumValues}}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Converter={StaticResource EnumConverter}}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

那么我的代码是:

public enum MyEnum
{
    [Description("foo")]
    Foo,
    [Description("bar")]
    Bar
}

public class EnumConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        FieldInfo field_info = value.GetType().GetField(value.ToString());
        object[] attributes = field_info.GetCustomAttributes(false);
        if (attributes.Length == 0)
            return value.ToString();
        else
        {
            DescriptionAttribute attribute = attributes[0] as DescriptionAttribute;
            return attribute.Description;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

现在是奇怪的部分。我启动程序并从组合框中 select 一个值(这一步很重要)。一切都按预期工作。然后我通过远程桌面连接到计算机。我立即在 Convert() 函数的第一行收到 NullReferenceException。 Type参数为字符串,除此之外没有太多信息可以排查,调用栈为空

您的静态资源中没有任何内容。或者找不到。打开您的输出 window 以查看此视图​​出现时的绑定错误。

Binding Source={StaticResource MyEnumValues}}

为什么?因为如果您在下面的 ToString() 上得到 null,那很可能意味着该值本身为 null。

  Enum myEnum = (Enum)value;
  var stringValue = myEnum.ToString();

如果我对你的描述的理解正确,当你通过 RDP 连接时抛出异常的程序实例是你在计算机上使用直接 [=29] 启动的同一个实例 =] session。 IE。您首先坐在计算机前启动程序,然后通过 RDP 接管同一用户 session 并与 已有的 运行 程序交互。

正确吗?

如果是这样,那么这是正常行为。切换到 RDP 连接会导致 WPF 程序丢失其所有视频资源,因为它不再渲染到本地视频卡,而是渲染到用于 RDP 的虚拟化视频驱动程序。因此,WPF 必须重建 UI。在这样做的过程中,您的绑定暂时具有 null 值。在此期间调用转换器,您在调用 ToString() 时没有首先检查 null 值,这导致 NullReferenceException.

由于您不可能可靠地强制 WPF 在 RDP session 上下文中改变其方式,唯一可行的解​​决方案是检查 valuenull 值,并在这种情况下做一些合理的事情(例如 return Binding.DoNothing;)。一旦 WPF 稳定下来,它应该回到您再次拥有实际值的状态,您将回到正常状态。