WPF Converter и NotifyOnTargetUpdated эксклюзив в привязке - PullRequest
2 голосов
/ 16 июня 2010

У меня проблема с привязкой данных в 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 Ответ

2 голосов
/ 16 июня 2010

Если вы получаете исключение XamlParseException, это означает, что эта ошибка происходит во время инициализации этого элемента управления.

Если указано NotifyOnTargetUpdated=True, событие TargetUpdated вызывается внутри вашего вызова InitializeComponent.На данный момент невероятно сомнительно, что у вас есть DataContext, поэтому привязка будет иметь нулевое значение.Обычно проблем нет, но вы запрашиваете событие, которое будет вызвано при обновлении свойства.

Итак, ваш обработчик событий попадает с нулевым значением textBlock.Contenu, вы передаете его в первый параметрFormattedText (который называется textToFormat), и он вызывает исключение ArgumentNullException.

Потренируйтесь в некотором защитном программировании и проверьте значение textBlock.Contenu на ноль перед запуском кода.

Два совета на будущеессылка:

1) При получении исключения вставьте всю трассировку стека, включая InnerException (поэтому вызовите Exception.ToString).Чаще всего вы увидите, где это происходит.Если нет, то кто-то здесь увидит, где это происходит, гораздо быстрее, чем вы получили ваш ответ.

2) Получая исключение, вы не знаете, откуда оно выдается (и вы явно этого не делаетеили вы видели бы это в своем коде), вынудите Visual Studio нарушить все исключения.http://msdn.microsoft.com/en-us/library/d14azbfh(VS.80).aspx

(Обратите внимание, что в зависимости от ваших настроек, пункт меню, на который они ссылаются, может присутствовать или отсутствовать. Вы также можете использовать клавиши CTRL + ALT + E, чтобы открыть диалоговое окно «Исключения».)

При таком наборе отладчик остановится на той строке кода, которая выдает исключение.

...