WPF - исключение NullReferenceException для isEnabled - PullRequest
4 голосов
/ 13 июня 2011

Я новичок в WPF, в прошлом я использовал Windows Forms. У меня тут проблема, и мне нравится, когда мне кто-то объясняет. Ниже приведен очень простой пример.

У меня есть страница XAML, на которой у меня есть один флажок, кнопка и текстовое поле. Флажок установлен по умолчанию.

Когда флажок снят, я хочу включить кнопку и текстовое поле, например,

private void UseDefaultFoldersCB_Checked(object sender, RoutedEventArgs e)
{
      //MessageBox.Show("");
      if (StartDirLocationTB.IsEnabled == false)
      {
           StartDirLocationTB.IsEnabled = true;
      }

      if (SelectStartLocationBtn.IsEnabled == false)
      {
            SelectStartLocationBtn.IsEnabled = true;
      }
}

XAML:

<CheckBox Content="Use Default Folders" IsChecked="True" Height="16" HorizontalAlignment="Left" Margin="10,14,0,0" Name="UseDefaultFoldersCB" VerticalAlignment="Top" Checked="UseDefaultFoldersCB_Checked" />
<TextBox Height="23" IsEnabled="False" HorizontalAlignment="Left" Margin="9,38,0,0" Name="StartDirLocationTB" VerticalAlignment="Top" Width="403" Background="WhiteSmoke" />
<Button Content="Select Start Folder" IsEnabled="False" Height="23" HorizontalAlignment="Right" Margin="0,38,6,0" Name="SelectStartLocationBtn" VerticalAlignment="Top" Width="139" />

Трассировка стека:

System.NullReferenceException было не обрабатывается кодом пользователя
Сообщение = ссылка на объект не установлена ​​на экземпляр объекта.
Source = TestProject StackTrace: at TestProject.MainWindow.UseDefaultFoldersCB_Checked (Object отправитель, RoutedEventArgs e) в C: \ Users \ х \ Desktop \ Test \ TestProject \ MainWindow.xaml.cs: линия 611 в System.Windows.EventRoute.InvokeHandlersImpl (Object источник, RoutedEventArgs args, логическое значение ререйз) в System.Windows.UIElement.RaiseEventImpl (DependencyObject отправитель, RoutedEventArgs args) в System.Windows.Controls.Primitives.ToggleButton.OnIsCheckedChanged (DependencyObject d, DependencyPropertyChangedEventArgs е) в System.Windows.DependencyObject.OnPropertyChanged (DependencyPropertyChangedEventArgs е) в System.Windows.FrameworkElement.OnPropertyChanged (DependencyPropertyChangedEventArgs е) в System.Windows.DependencyObject.NotifyPropertyChange (DependencyPropertyChangedEventArgs арг) в System.Windows.DependencyObject.UpdateEffectiveValue (EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata метаданные, EffectiveValueEntry oldEntry, EffectiveValueEntry & newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) в System.Windows.DependencyObject.SetValueCommon (DependencyProperty дп, значение объекта, PropertyMetadata метаданные, логические coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) в System.Windows.DependencyObject.SetValue (DependencyProperty дп, значение объекта) в MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue (Object inst, свойство XamlMember, Object значение)

Когда я запускаю приложение из Visual Studio, я получаю исключение NullReferenceException для приведенного выше кода. Почему этот код выполняется при запуске приложения? Я бы подумал, что он будет выполняться только тогда, когда флажок установлен / снят? Почему исключение NullReferenceException?

Спасибо.

Ответы [ 4 ]

6 голосов
/ 13 июня 2011

Ответ - прекратить кодирование, как будто вы находитесь в WinForms.Вместо этого используйте привязку данных.Я нашел хороший образец для вас здесь .Если вы все еще хотите сделать это в обработчиках событий, оставьте это в событии «Проверено» и просто добавьте нулевые проверки.Если вы используете событие Click, сочетания клавиш не будут работать.Нулевой проверочный образец:

private void UseDefaultFoldersCB_Checked(object sender, RoutedEventArgs e)
{
    if (StartDirLocationTB != null && StartDirLocationTB.IsEnabled == false)
    {
         StartDirLocationTB.IsEnabled = true;
    }

    if (SelectStartLocationBtn != null && SelectStartLocationBtn.IsEnabled == false)
    {
         SelectStartLocationBtn.IsEnabled = true;
    }
}
3 голосов
/ 13 июня 2011

Установщики свойств в XAML будут вызывать события, связанные с изменением этих свойств, как если бы они были заданы в коде (более или менее). Я полагаю, что в тот момент, когда синтаксический анализатор XAML устанавливает свойство через ваш IsChecked = "True", обработчик событий срабатывает - и в этот момент ваши другие объекты, определенные в XAML, не были созданы.

(Кстати, это одно из тех мест, где Silverlight и WPF обычно различаются в деталях).

2 голосов
/ 13 июня 2011

Причина, по которой вы получаете вызов для этого обработчика событий, заключается в том, что при инициализации страницы, XAML-анализатор видит, что событие связано с атрибутом Checked флажка (т.е. это событие будет вызываться, когда когда-либо свойство IsChecked флажка имеет значение true)таким образом, он вызывает событие во время самой загрузки.

Я предлагаю вам использовать событие-флажок Click, чтобы вы могли иметь событие при каждом изменении состояния флажка.

Таким образом, у вас XAML будет что-то вроде этого.

<CheckBox Content="Use Default Folders" IsChecked="True" Height="16" HorizontalAlignment="Left" Margin="10,14,0,0" Name="UseDefaultFoldersCB" VerticalAlignment="Top" Click="UseDefaultFoldersCB_Click" />
<TextBox Height="23" IsEnabled="False" HorizontalAlignment="Left" Margin="9,38,0,0" Name="StartDirLocationTB" VerticalAlignment="Top" Width="403" Background="WhiteSmoke" />
<Button Content="Select Start Folder" IsEnabled="False" Height="23" HorizontalAlignment="Right" Margin="0,38,6,0" Name="SelectStartLocationBtn" VerticalAlignment="Top" Width="139" />

, а код Eventhandler останется таким же, как ..

private void UseDefaultFoldersCB_Click(object sender, RoutedEventArgs e)
{
      //MessageBox.Show("");
      if (StartDirLocationTB.IsEnabled == false)
      {
           StartDirLocationTB.IsEnabled = true;
      }

      if (SelectStartLocationBtn.IsEnabled == false)
      {
            SelectStartLocationBtn.IsEnabled = true;
      }
}
1 голос
/ 13 июня 2011

Я не думаю, что парсер XAML в WPF гарантирует порядок, в котором будут присоединены различные свойства и обработчики событий.Я думаю, что в вашем случае сначала он подключает ваш обработчик UseDefaultFoldersCB_Checked, а затем устанавливает IsChecked в значение true, которое вызывает событие.

Вы можете немного расширить свой вопрос, предоставив стек вызовов при возникновении исключения.

...