WPF Converter和NotifyOnTargetUpdated在绑定中独占?

时间:2010-06-16 10:35:27

标签: wpf data-binding exception ivalueconverter

我在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;
}

处理程序的作用是根据内容的长度调整控件的大小。这很难看,但我希望在重构之前让功能部件工作。

1 个答案:

答案 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打开“例外”对话框。)

使用此设置,调试器将停止抛出异常的确切代码行。