我的 C#/.NET 应用程序中出现异常,内容如下:
“CommandCoverter”无法将“MyNamespace.MyDerivedFromICommandSubclass”转换为“System.String”。
我正在做的事情相当简单,正如 MSDN ICommand 文档:
public class MyDerivedFromICommandSubclass : ICommand
{
// Implement interface
...
}
我有一个 FlowDocument 带有 超链接 关于它。超链接允许有一个命令 属性,我将其设置为派生的 ICommand,以便单击链接时执行我的自定义操作。
那部分有效。
这就是我遇到麻烦的地方:如果我选择超链接并右键单击“复制”(或按 Control-C)。
.NET 框架立即抛出 System.NotSupportedException 以及上面的异常详细信息。堆栈跟踪显示:
在System.ComponentModel.TypeConverter.GetConvertToException(对象值,类型destinationType)
在 System.Windows.Input.CommandConverter.ConvertTo(ITypeDescriptorContext 上下文、CultureInfo 区域性、对象值、类型目标类型)
此时,我诉诸于 Red Gate 的免费 .NET Reflector 并查看了 ConvertTo
的源代码:
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == null) // We know it isn't, it's System.String
{
throw new ArgumentNullException("destinationType"); // We don't see this exception
}
if (destinationType == typeof(string)) // It is, so control passes in
{
if (value == null) // It isn't, so this condition is skipped
{
return string.Empty; // Confirmed we don't get this return value
}
RoutedCommand command = value as RoutedCommand;
if (((command != null) && (command.OwnerType != null) && IsKnownType(command.OwnerType))
{ // Is a user-defined ICommand a known type? Doubtful. This gets skipped.
return command.Name; // Confirmed we don't get this return value
}
// It has to fall through then if no return is done!
}
throw base.GetConvertToException(value, destinationType); // BOOM!
// value is my custom ICommand and destinationType is System.String
}
所以问题就变成了,因为所有这些都发生在 .NET 内部,我做错了什么吗?如果是,怎么办?或者,这是一个 .NET 错误吗?如果是,是否有解决方法?
感谢您的任何帮助。
I'm getting an exception in my C#/.NET application that reads:
'CommandCoverter' is unable to convert 'MyNamespace.MyDerivedFromICommandSubclass' to 'System.String'.
What I'm doing is fairly straight forward, as described by the MSDN ICommand documentation:
public class MyDerivedFromICommandSubclass : ICommand
{
// Implement interface
...
}
I have a FlowDocument with a Hyperlink on it. The Hyperlink is allowed to have a Command Property, which I set to my derived ICommand so that when the link is clicked, my custom action gets performed.
That part works.
Here's where I get into trouble: if I select the hyperlink and right-click Copy (or press Control-C).
Instantly the .NET framework throws a System.NotSupportedException with the exception detail above. The stack trace shows:
at System.ComponentModel.TypeConverter.GetConvertToException(Object value, Type destinationType)
at System.Windows.Input.CommandConverter.ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object value, Type destinationType)
At this point I resorted to Red Gate's free .NET Reflector and looked at the source code to ConvertTo
:
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == null) // We know it isn't, it's System.String
{
throw new ArgumentNullException("destinationType"); // We don't see this exception
}
if (destinationType == typeof(string)) // It is, so control passes in
{
if (value == null) // It isn't, so this condition is skipped
{
return string.Empty; // Confirmed we don't get this return value
}
RoutedCommand command = value as RoutedCommand;
if (((command != null) && (command.OwnerType != null) && IsKnownType(command.OwnerType))
{ // Is a user-defined ICommand a known type? Doubtful. This gets skipped.
return command.Name; // Confirmed we don't get this return value
}
// It has to fall through then if no return is done!
}
throw base.GetConvertToException(value, destinationType); // BOOM!
// value is my custom ICommand and destinationType is System.String
}
So the question then becomes, as all of this happens inside of .NET, am I doing something wrong, and if so, what? Or, is this a .NET bug, and if so, is there a work around?
Thanks for any help.
发布评论
评论(5)
直觉上感觉这是错误的。复制超链接应该复制文本,无论命令执行什么操作。但是,您可以通过为命令类实现自己的 TypeConverter 来解决该问题 (如何实现类型转换器)。让它委托给 CommandConverter,CanConvertTo 除外:从该方法返回 false 以告诉框架您的命令无法转换为字符串(或者也将 CanConvertTo 委托给 CommandConverter,然后从 ConvertTo 返回一个代表字符串。
Intuitively this feels wrong; copying the hyperlink should copy the text, regardless of what the command does. However, you can work around the problem by implementing your own TypeConverter for your command class (How to Implement a Type Converter). Have it delegate to CommandConverter, except for CanConvertTo: return false from that method to tell the framework that your command cannot be converted to a string (or delegate CanConvertTo to CommandConverter also, then return a representative string from ConvertTo.
ICommand 的精彩描述位于此 SkySigal 的博客条目,尽管我需要Google 缓存 由于当时的博客配置问题。不幸的是,解决此问题的文章末尾关于 ICommand 应该是静态还是非静态的措辞有点含糊。
然而,事实证明,有一篇关于 dotnet 狂热的文章谈论如何复制带有自定义命令的超链接将使应用程序崩溃。
看来这个 bug 至少自 2007 年以来就一直存在于 .NET 中,问题在于代码显式检查“已知命令”,正如上面的 Reflector 分析所示。
.NET 希望将命令及其父对象序列化,这就是问题所在。本文的解决方案涉及创建一个辅助对象,该对象被序列化过程忽略,该对象执行与命令相同的操作。
myns 命名空间的 HyperlinkHelper 类中包含
一些支持代码,作为名为 Command 的属性。这是一个聪明的诡计,而且应该是可耻的不必要的。
向Eric Burke 致敬,他解决了这个问题。
A fantastic description of ICommand resides in this blog entry by SkySigal, though I needed Google's Cache due to blog configuration issues at the time. Unfortunately, the end of the article where this problem is addressed is a little ambiguous in its wording about whether the ICommand should be static or non-static.
Turns out, however, there was an article on dotnet mania talking about how copying a hyperlink with a custom command will crash an application.
Seems this bug has been in .NET since 2007, at least, and that the problem is the code explicitly checking for "known commands," just as the Reflector analysis above showed.
.NET wants to serialize the command along with its parent object, and that's where the problem comes in. The article's solution involves creating a helper object, which is ignored by the serialization process, which does the same thing as the command.
becomes
with some backing code inside the myns namespace's HyperlinkHelper class as a property named Command. It's clever trickery, and ought to be shamefully unnecessary.
Hats off to Eric Burke for figuring this one out.
也让我的头在这上面撞了好一阵子。我本来会将此添加为对沃尔特·斯通伯恩纳(Walt Stoneburner)的答案的评论,但目前似乎首先需要更多的要点才能做到这一点。
反正。由于原始解决方案的链接似乎已损坏,我又进行了一些谷歌搜索。我目前正在运行 .Net Framework 版本 4,这似乎仍然没有解决(!)
Microsoft 发布了一个错误问题,再加上一个已花费的解决方法,我认为这是 Walt Stoneburner 所描述的类似解决方案。您只需使用另一个创建的依赖属性,而不是复制粘贴时麻烦的“Command”属性,其余的由辅助类处理。您可以从此处下载 zip,按“显示链接”进行访问。感谢 Bob Bao 发布它:
http://connect.microsoft.com/VisualStudio/feedback/details/637269/copying-a-command-bound-hyperlink-in-a-flowdocument-throws-an-exception
微软现在似乎已经发布了一个解决方案,它被称为“HyperlinkHelper”。由于一些尴尬的原因,他们似乎选择将其与某些团队基础 dll 一起分发(?)您可以在下面的链接中找到它的文档。如果您足够幸运能够使用 Team Foundation 服务器,您甚至可以直接使用该类。否则,我建议重复使用上面提供的解决方案。
http://technet.microsoft.com/en-us /subscriptions/microsoft.teamfoundation.controls.wpf.hyperlinkhelper
Also banged my head on this one for quite a while. I would have added this as a comment to Walt Stoneburner's answer but seem to need more points first to do that currently.
Anyway. As the link to the original solution seem to be broken I did some more googling. I am currently running .Net Framework version 4 and this still seems to be very much unresolved (!)
There is a bug issue posted to Microsoft and together with that a spended workaround, I would think it is a similar solution as described by Walt Stoneburner. You just use another created dependency property instead of the troublesome 'Command' property on copy-paste, the rest is treated by the helper class. You can download a zip from here, press the 'Show link' to access it. Thanks Bob Bao for posting it:
http://connect.microsoft.com/VisualStudio/feedback/details/637269/copying-a-command-bound-hyperlink-in-a-flowdocument-throws-an-exception
Microsoft seem to have released a solution by now, 'HyperlinkHelper' it is called. For some awkward reason they seem to have choosen to distribute it with in some team foundation dll(?) You can find documentation for it on the link below. If you are fortunate enough to be using Team Foundation server you might even be able to use the class directly. Otherwise, I would recommend reusing the solution provided above.
http://technet.microsoft.com/en-us/subscriptions/microsoft.teamfoundation.controls.wpf.hyperlinkhelper
我刚刚在一个小型 POC 中遇到了这个问题,尽管我让它在一个更大的项目中工作,并且我设法找到了原因。不知道它是否有帮助,但这里是他的背景和解决方案。
当尝试将命令绑定到 Xceed 数据网格中的按钮时出现问题,该 itemSource 绑定在我的 viewModel 中公开的集合上。
观点:
视图模型
适配器(然后将由数据网格中的一行表示)。中继命令是基本的 ICommand 实现。
这是我的应用程序尝试创建适配器并将其添加到集合中时生成的异常
System.NotSupportedException 未处理
Message="'CommandConverter' 无法将 'UnIfied.Module.UI.Client.Adapters.RelayCommand' 转换为 'System.String'。"
来源=“系统”
堆栈跟踪:
在System.ComponentModel.TypeConverter.GetConvertToException(对象值,类型destinationType)
在 System.Windows.Input.CommandConverter.ConvertTo(ITypeDescriptorContext 上下文、CultureInfo 区域性、对象值、类型目标类型)
在System.ComponentModel.TypeConverter.ConvertTo(对象值,类型destinationType)
在 System.Windows.Controls.ContentPresenter.DefaultTemplate.DoDefaultExpansion(TextBlock 文本块,对象内容,ContentPresenter 容器)
(等等)
该问题是由于我的数据网格配置为 AutoCreateColumns(即基于适配器的属性)而引起的。只需将此属性更改为 false,然后一切又恢复正常。
希望这会对你们有所帮助!
——布鲁诺
I just ran into this issue, in a small POC althought I got it to work in a bigger project and I managed to find why. Don't know if it can helps, but here his the context and the solution.
The problem appeared when trying to bind a command to a Button in an Xceed datagrid, which itemSource was bind on a collection exposed in my viewModel.
THE VIEW :
THE VIEWMODEL
THE ADAPTER (which will then be represented by a row in the datagrid). Relay command is a basic ICommand implementation.
And here is the exception generated as soon as my app tried to create an adapter and add it to the collection
System.NotSupportedException was unhandled
Message="'CommandConverter' is unable to convert 'UnIfied.Module.UI.Client.Adapters.RelayCommand' to 'System.String'."
Source="System"
StackTrace:
at System.ComponentModel.TypeConverter.GetConvertToException(Object value, Type destinationType)
at System.Windows.Input.CommandConverter.ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object value, Type destinationType)
at System.ComponentModel.TypeConverter.ConvertTo(Object value, Type destinationType)
at System.Windows.Controls.ContentPresenter.DefaultTemplate.DoDefaultExpansion(TextBlock textBlock, Object content, ContentPresenter container)
(ETC.)
The issue was caused by the fact that my datagrid was configured to AutoCreateColumns (i.e. based on the properties of the adapter). Just switched this property to false and then all went straight again.
Hope this will help you guys !
--Bruno
解决此问题的简单方法是使命令与动态资源绑定,以便解析器在尝试将命令转换为字符串时不会解析。
在此处查看此解决方案的详细信息 http://ciintelligence.blogspot .com/2011/11/wpf-copying-hyperlink-with-command.html
The easy way to solve this issue to make Command binding with dynamic resource so that parser do not resolve while trying to convert command to string.
Check details of this solution here http://ciintelligence.blogspot.com/2011/11/wpf-copying-hyperlink-with-command.html