WPF窗口一闪而过,那你可能遇到空引用了

情况之一:ListBox中SelectionChanged与IsSelected引发的空引用

同时在ListBox使用了SelectionChanged属性,并且在其ListItem中使用了IsSelected属性。
而一旦这样做,那么在初始化函数InitializeComponent()执行的时候,IsSelected会使SelectionChanged事件被触发。
MainWinow.xaml

<Window x:Class="NullRefDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="空引用示例" Height="300" Width="400">
    <Grid Margin="10">
        <Grid.ColumnDefinitions>
            <!-- 左侧导航 -->
            <ColumnDefinition Width="120"/>
            <!-- 右侧内容 -->
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <!-- ❗ 注意:ListBox 在 ContentControl 之前定义 -->
        <ListBox x:Name="NavList" Grid.Column="0"
                 SelectionChanged="NavList_SelectionChanged">
            <ListBoxItem IsSelected="True">首页</ListBoxItem>
            <ListBoxItem>设置</ListBoxItem>
            <ListBoxItem>关于</ListBoxItem>
        </ListBox>

        <!-- 内容区(x:Name="MainContent")定义在 ListBox 之后 -->
        <ContentControl x:Name="MainContent" Grid.Column="1" />
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace NullRefDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void NavList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // ❌ 错误:这里的 MainContent 可能还是 null!
            // 因为 InitializeComponent 先构造 ListBox,触发事件,
            // 然后才会构造 ContentControl 并赋值给 MainContent 字段。
            switch (NavList.SelectedIndex)
            {
                case 0:
                    MainContent.Content = new TextBlock { Text = "这是首页" };
                    break;
                case 1:
                    MainContent.Content = new TextBlock { Text = "这是设置" };
                    break;
                case 2:
                    MainContent.Content = new TextBlock { Text = "这是关于" };
                    break;
            }
        }
    }
}

清注意!这时ListBox后面的标签还没有初始化,也就是说后面的x:Name=null。
这个例子是x:Name="MainContent",此时MainContent = null,如果这时SelectionChanged事件用到MainConten,就会触发空引用。

解决方法一:

private void NavList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // ✅ 如果 MainContent 还没初始化好,直接返回,等它好了再响应
    if (MainContent == null) return;
    switch (NavList.SelectedIndex)
    {
        // ... 同上的赋值逻辑
    }
}

解决方法二:
删掉ListItem中的IsSelected属性,像下面这样写

public MainWindow()
{
    InitializeComponent();
    // 在 InitializeComponent 完成后再设选中项,此时所有控件均已就绪
    NavList.SelectedIndex = 0;
}

我更建议使用方法二

posted @ 2026-05-09 20:09  汇集电力  阅读(17)  评论(0)    收藏  举报