WPF - isEnabled上的NullReferenceException

时间:2011-06-13 08:40:11

标签: c# wpf isenabled

我是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是   未按用户代码处理
  Message =对象引用未设置为   对象的实例。
  Source = TestProject StackTrace:          在TestProject.MainWindow.UseDefaultFoldersCB_Checked(对象   发件人,RoutedEventArgs e)in   C:\用户\ JC \桌面\测试\ TestProject \ MainWindow.xaml.cs:行   611          在System.Windows.EventRoute.InvokeHandlersImpl(Object   source,RoutedEventArgs args,Boolean   再加注)          在System.Windows.UIElement.RaiseEventImpl(DependencyObject   sender,RoutedEventArgs args)          在System.Windows.Controls.Primitives.ToggleButton.OnIsCheckedChanged(DependencyObject)   d,DependencyPropertyChangedEventArgs   E)          在System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs)   E)          在System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs)   E)          在System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs)   参数)          在System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex   entryIndex,DependencyProperty dp,   PropertyMetadata元数据,   EffectiveValueEntry oldEntry,   EffectiveValueEntry&安培; newEntry,布尔值   coerceWithDeferredReference,布尔值   coerceWithCurrentValue,OperationType   operationType)          在System.Windows.DependencyObject.SetValueCommon(DependencyProperty   dp,对象值,PropertyMetadata   元数据,布尔值   coerceWithDeferredReference,布尔值   coerceWithCurrentValue,OperationType   operationType,Boolean isInternal)          在System.Windows.DependencyObject.SetValue(DependencyProperty   dp,对象值)          在MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object   inst,XamlMember属性,Object   值)

当我从Visual Studio启动应用程序时,我在上面的代码中得到一个NullReferenceException。为什么在应用程序启动时执行此代码?我曾经以为它只会在选中/取消选中复选框时执行?为什么NullReferenceException?

感谢。

4 个答案:

答案 0 :(得分:7)

答案是停止编码,就好像你在WinForms中一样。请改用数据绑定。我找到了一个很好的样本here。如果您仍想在事件处理程序中执行此操作,请将其保留在“已检查”事件中,并添加空检查。如果您使用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;
    }
}

答案 1 :(得分:4)

XAML中的属性设置器将导致与这些属性相关的事件发生变化,就好像它们是在代码中设置的(或多或少)。我相信XAML解析器通过您的IsChecked =“True”设置属性,事件处理程序触发 - 此时您在XAML中定义的其他对象尚未实例化。

(顺便说一句,这是Silverlight和WPF在细节上往往不同的地方之一)。

答案 2 :(得分:3)

您在此事件处理程序上接收调用的原因是,在初始化页面时,XAML调度程序发现事件附加到Checkbox的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;
      }
}

答案 3 :(得分:1)

我认为WPF中的XAML解析器不保证将附加不同属性和事件处理程序的顺序。我认为在您的情况下,首先它会附加您的UseDefaultFoldersCB_Checked处理程序,然后将IsChecked设置为true来触发事件。

当发生异常时,您可以通过提供调用堆栈来扩展您的问题。