通过远程桌面连接时出现 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 上下文中改变其方式,唯一可行的解决方案是检查 value
的 null
值,并在这种情况下做一些合理的事情(例如 return Binding.DoNothing;
)。一旦 WPF 稳定下来,它应该回到您再次拥有实际值的状态,您将回到正常状态。
这是一个奇怪的错误。我将枚举绑定到组合框并显示描述属性。我正在使用 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 上下文中改变其方式,唯一可行的解决方案是检查 value
的 null
值,并在这种情况下做一些合理的事情(例如 return Binding.DoNothing;
)。一旦 WPF 稳定下来,它应该回到您再次拥有实际值的状态,您将回到正常状态。