Slider控件ValueChanged事件报错:更新标签出现空引用异常
解决WPF Slider值变化时的空引用异常问题
需求与问题场景
要实现:Slider控件值为1时,标签显示Player;值大于1时显示Players。编写的代码运行时触发Object reference not set to an instance of an object空引用异常,即使Slider初始值设为2,仍在else分支报错。
现有代码
XAML代码
<Viewbox Grid.Column="1" Margin="10"> <Slider x:Name="sliderhunter" Minimum="1" Maximum="8" Width="200" TickFrequency="1" Value="2" TickPlacement="BottomRight" ValueChanged="sliderhunter_ValueChanged" Margin="10" IsMoveToPointEnabled="True" IsSnapToTickEnabled="True"/> </Viewbox> <TextBox Grid.Column="1" IsHitTestVisible="False" Foreground="White" Text="{Binding Value, ElementName=sliderhunter, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Left" Height="68" VerticalAlignment="Top" FontSize="50" Background="Transparent" HorizontalContentAlignment="Left" BorderBrush="Transparent" Margin="43,34,469,0" /> <Label Grid.Column="1" IsHitTestVisible="False" x:FieldModifier="Public" Content="Hunters" HorizontalContentAlignment="Left" Height="80" VerticalAlignment="Top" FontSize="50" Background="Transparent" BorderBrush="Transparent" Margin="95,34,343,0" x:Name="txtHunter" />
后台VB代码
Private Sub sliderhunter_ValueChanged(sender As Object, e As RoutedPropertyChangedEventArgs(Of Double)) Handles sliderhunter.ValueChanged If e.NewValue > 1 Then txtHunter.Content = "Players" Else txtHunter.Content = "Player" End If End Sub
错误信息
System.NullReferenceException HResult=0x80004003 Message=Object reference not set to an instance of an object. Source=GameProject StackTrace: at GameProject.winSetGameSettings.sliderhunter_ValueChanged(Object sender, RoutedPropertyChangedEventArgs`1 e) in C:\Users\mgobl\source\repos\GameScoreBoard\GameScoreboard\winSetGameSettings.xaml.vb:line 2571
问题原因
空引用异常的核心原因是:Slider的初始值Value="2"会在窗口控件初始化完成前触发ValueChanged事件,此时txtHunter标签还没被实例化(未创建对象),代码里访问txtHunter.Content自然会报错。
新手友好的解决方案
方案一:先判断控件是否初始化完成(最简单快速)
修改后台VB代码,在操作txtHunter前先检查它是否已创建:
Private Sub sliderhunter_ValueChanged(sender As Object, e As RoutedPropertyChangedEventArgs(Of Double)) Handles sliderhunter.ValueChanged ' 如果标签还没初始化,直接退出事件 If txtHunter Is Nothing Then Return If e.NewValue > 1 Then txtHunter.Content = "Players" Else txtHunter.Content = "Player" End If End Sub
方案二:延迟初始值设置(避免加载时触发事件)
- 先移除XAML中Slider的
Value="2"属性,防止加载时提前触发事件:
<Slider x:Name="sliderhunter" Minimum="1" Maximum="8" Width="200" TickFrequency="1" TickPlacement="BottomRight" ValueChanged="sliderhunter_ValueChanged" Margin="10" IsMoveToPointEnabled="True" IsSnapToTickEnabled="True"/>
- 在窗口的
Loaded事件中设置初始值,此时所有控件都已初始化:
Private Sub winSetGameSettings_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded ' 设置Slider初始值 sliderhunter.Value = 2 ' 同步标签内容 txtHunter.Content = "Players" End Sub
方案三:使用数据绑定(符合WPF设计思想,一劳永逸)
不需要编写后台事件,通过值转换器直接绑定Slider的值到Label的Content:
- 创建一个值转换器类(在项目中添加新的VB类):
Public Class PlayerCountConverter Implements IValueConverter Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.Convert ' 把Slider的Double值转换为对应的文本 Dim count As Double = CDbl(value) Return If(count > 1, "Players", "Player") End Function Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack ' 反向转换不需要,返回Nothing即可 Return Nothing End Function End Class
- 在XAML的窗口资源中声明转换器(注意替换命名空间为你的项目命名空间):
<Window x:Class="GameProject.winSetGameSettings" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:GameProject" ' 这里是你的项目命名空间 mc:Ignorable="d" Title="winSetGameSettings" Height="450" Width="800"> <Window.Resources> <!-- 声明转换器 --> <local:PlayerCountConverter x:Key="PlayerCountConverter"/> </Window.Resources> <!-- 你的其他XAML内容 --> </Window>
- 修改Label的Content绑定,使用转换器:
<Label Grid.Column="1" IsHitTestVisible="False" x:FieldModifier="Public" Content="{Binding Value, ElementName=sliderhunter, Converter={StaticResource PlayerCountConverter}}" HorizontalContentAlignment="Left" Height="80" VerticalAlignment="Top" FontSize="50" Background="Transparent" BorderBrush="Transparent" Margin="95,34,343,0" x:Name="txtHunter" />
这样Slider值变化时,Label内容会自动更新,完全不需要后台事件,也不会有初始化问题。
内容的提问来源于stack exchange,提问作者ExpertOnNothing
相关产品推荐
相关产品推荐

