我在WPF中遇到数据绑定问题。
当我尝试使用值转换器并将NotifyOnTargetUpdated = True属性设置为True时,我收到XamlParseException并显示以下消息:
'System.Windows.Data.BindingExpression' 值不能分配给属性 'Contenu'的对象 'View.UserControls.ShadowedText'。 值不能为空。参数名称: textToFormat对象错误 'System.Windows.Data.Binding'中 标记文件 'View.UserControls;组件/ saletotal.xaml' 第363行位置95。
绑定非常标准:
<my:ShadowedText Contenu="{Binding Path=Total,
Converter={StaticResource CurrencyToStringConverter},
NotifyOnTargetUpdated=True}"
TargetUpdated="MontantTotal_TargetUpdated">
</my:ShadowedText>
(为了简洁而删除了样式属性)
当NotifyOnTargetUpdated = True被删除时,转换器存在于资源中并正常工作。类似地,TargetUpdated事件被正确调用和实现,并在转换器被删除时起作用。
注意:此绑定在ControlTemplate中定义,但我认为这与问题无关。
有人能解释我发生了什么吗?我定义绑定错了吗?这些特征是否相互排斥(在这种情况下,你能解释为什么会这样)吗?
提前致谢。
更多信息:以下是TargetUpdated处理程序的内容:
private void MontantTotal_TargetUpdated(object sender, DataTransferEventArgs e)
{
ShadowedText textBlock = (ShadowedText)e.TargetObject;
double textSize = textBlock.Taille;
double delta = 5;
double defaultTaille = 56;
double maxWidth = textBlock.MaxWidth;
while (true)
{
FormattedText newFormat = new FormattedText(textBlock.Contenu,
CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
new Typeface("Calibri"), textSize,
(SolidColorBrush) Resources["RougeVif"]);
if (newFormat.Width < textBlock.MaxWidth && textSize <= defaultTaille)
{
if ((Math.Round(newFormat.Width) + delta) >= maxWidth || textSize == defaultTaille)
{
break;
}
textSize++;
}
else
{
if ((Math.Round(newFormat.Width) - delta) <= maxWidth && textSize <= defaultTaille)
{
break;
}
textSize--;
}
}
textBlock.Taille = textSize;
}
处理程序的作用是根据内容的长度调整控件的大小。这很难看,但我希望在重构之前让功能部件工作。
答案 0 :(得分:2)
如果您收到XamlParseException,则表示在此控件初始化期间发生此错误。
如果指定了NotifyOnTargetUpdated=True
,则会在InitializeComponent调用中引发TargetUpdated事件。此时,您有一个DataContext令人难以置信地怀疑,因此绑定将评估为null。通常,没有问题,但是您要求在更新属性时引发事件。
所以它使用null textBlock.Contenu
值命中你的事件处理程序,你将它传递给FormattedText的第一个参数(名为textToFormat
)并且它抛出一个ArgumentNullException。
练习一些防御性编程,并在运行代码之前检查textBlock.Contenu
值为null。
以下参考的两个提示:
1)当收到异常时,粘贴整个堆栈跟踪,包括InnerException(因此调用Exception.ToString)。通常情况下,你会看到它发生的地方。如果没有,那么这里的某个人会比你得到答案更快地看到它发生的地方。
2)当收到异常时,你不知道它被抛出的位置(你显然没有,或者你已经在代码中看到它),强制Visual Studio打破所有异常。 http://msdn.microsoft.com/en-us/library/d14azbfh(VS.80).aspx
(请注意,根据您的设置,它们引用的菜单项可能也可能不存在。您也可以使用CTRL + ALT + E打开“例外”对话框。)
使用此设置,调试器将停止抛出异常的确切代码行。