我是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?
感谢。
答案 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来触发事件。
当发生异常时,您可以通过提供调用堆栈来扩展您的问题。