2010-06-16 2 views
2

У меня проблема с привязкой данных в WPF.WPF Converter и NotifyOnTargetUpdated эксклюзив в привязке?

Когда я пытаюсь использовать преобразователь значений и установите NotifyOnTargetUpdated = True свойство Правда, я получаю XamlParseException со следующим сообщением:

«System.Windows.Data.BindingExpression» значение не может быть присваивается свойству 'Contenu' объекта 'View.UserControls.ShadowedText'. Значение не может быть нулевым. Имя параметра: textToFormat Ошибка в объекте 'System.Windows.Data.Binding' в разметки файлов 'View.UserControls; компонент/saletotal.xaml' Line 363 Позиция 95.

Связывание довольно стандарт:

<my:ShadowedText Contenu="{Binding Path=Total, 
            Converter={StaticResource CurrencyToStringConverter}, 
            NotifyOnTargetUpdated=True}" 
       TargetUpdated="MontantTotal_TargetUpdated"> 
</my:ShadowedText> 

(стайлинг свойство удалена для краткости)

преобразователь существует в ресурсах и работает правильно, когда NotifyOnTargetUpdated = Тр ue удаляется. Аналогично, событие 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

Вы делаете что-нибудь особенное в обработчике событий TargetUpdated? –

+0

Я не знаю, если это просто опечатка, но в привязке отсутствует запятая. Он должен выглядеть следующим образом: {Binding Path = Total, Converter = {StaticResource CurrencyToStringConverter}, NotifyOnTargetUpdated = True} –

+0

Это опечатка, я добавил разрывы строк в вопросе о читаемости, есть кома между конвертером и NotifyOnTargetUpdated частями в реальном исходном коде. Редактирование вопроса, чтобы исправить это. –

ответ

2

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

С учетом указанного NotifyOnTargetUpdated=True события TargetUpdated поднимаются внутри вашего вызова InitializeComponent. На данный момент невероятно сомнительно, что у вас есть DataContext, поэтому привязка будет оцениваться как 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, чтобы открыть диалоговое окно Исключения.)

С помощью этого набора, отладчик остановится на точной строке кода, бросающей исключение.

+0

Спасибо, это была именно проблема. Я не ожидал, что вообще будет вызвано во время инициализации элемента управления. –

Смежные вопросы