C#为什么在施法后为null

时间:2011-06-14 07:01:58

标签: c# wpf xaml nullreferenceexception

大家好请求帮助我,我很困惑,为什么我的代码在转换后为空 这是我的xaml代码

<Window.Resources>
    <Style x:Key="Menu" TargetType="{x:Type Border}">
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Width" Value="25" />
        <EventSetter Event="MouseLeftButtonUp" Handler="Menu_MouseLeftButtonUp" />
    </Style>
</Window.Resources>

<Grid>
    <Border Name="BorderCloseWindow" CornerRadius="0,8,0,0" 
            Style="{StaticResource Menu}">
        <Image Source="pack://application:,,,/images/icons/CloseSTD.png" />
    </Border>
</Grid>

这是处理边框的C#

private void Menu_MouseLeftButtonUp(object sender, RoutedEventArgs e)
{
    Border b = e.Source as Border;
    if (b.Name == "BorderCloseWindow")
    {
        this.Close();
    }
}

如果我在边框中按下鼠标按钮会产生这样的错误 你调用的对象是空的。 发生在

if(b.Name == "BorderCloseWindow")

请帮助我为什么给null?以及如何修复我的程序,以便运行。

6 个答案:

答案 0 :(得分:15)

显然,e.Source不属于Border类型。

The first thing you should fix is your cast.您正在使用

Border b = e.Source as Border;

如果null不是Border,则返回e.Source,导致后续的NullReferenceException。由于之后不检查null,因此应使用普通的强制转换:

Border b = (Border)e.Source;

这不会解决您的潜在问题,但会确保

  • 您获得了潜在问题的正确例外(InvalidCastException而不是NullReferenceException)和
  • 错误是在真正导致问题的行中抛出的(而不是以下if,这完全是无辜的。)

现在第二件事,问题的根源:RoutedEventsArgs.Source 您附加事件处理程序的边框(即,它不是控件处理事件)。它是引发事件的控件,可能是边框内的图像。有关详细信息,请参阅the documentation of RoutedEventArgs.Source

因此,要解决此问题,请使用发件人而不是e.Source

Border b = (Border)sender;

答案 1 :(得分:4)

发件人可能是Border,尝试首先将发件人转换为边框:

  Border b = sender as Border;

如果它没有帮助,只需在处理程序中设置断点,而不是打开监视窗口,您将看到sendere.Source的实际类型。

答案 2 :(得分:4)

首先,当演员表没有成功时,这就是as的表现。它以这种方式制作,以便您可以轻松检查它是否成功。如果你写了

Border b = (Border)e.Source;

它会抛出InvalidCastException

其次,e.Source包含您实际点击的对象,在本例中为Image。如果要访问处理事件的对象,请使用sender参数。

所以你的代码应该是这样的:

private void Menu_MouseLeftButtonUp(object sender, RoutedEventArgs e)
{
    Border b = (Border)sender;
    if (b.Name == "BorderCloseWindow")
    {
        this.Close();
    }
}

甚至更好,只是

private void Menu_MouseLeftButtonUp(object sender, RoutedEventArgs e)
{
    this.Close();
}

如果为要处理某些事件的每个Control设置不同的处理程序方法,这将有效。它不那么脆弱:如果你更改Border的名称(你甚至不需要命名),如果你不小心在XAML或C#中更改方法的名称,它仍然可以工作,你最有可能得到一个编译时错误。

答案 3 :(得分:2)

看来e.Source不是Border,所以e.Source as Border为null。 源可能是边框内的另一个对象,事件路由到边界。

您可以尝试使用

测试e.Source的类型
if (e.Source is Border)
{
}

或者您可以通过转发发件人而不是e.Source来获取边框对象。

答案 4 :(得分:1)

将您的代码更改为:

private void Menu_MouseLeftButtonUp(object sender, RoutedEventArgs e)        
{            
  System.Diagnostics.Debug.WriteLine(
    "Sender contains an object of type {0}", 
    sender.GetType());
  System.Diagnostics.Debug.WriteLine(
    "e.Source contains an object of type {0}", 
    e.Source.GetType());
}

当您触发事件时,您需要的信息将被写入输出窗口。您可能需要使用Visual Studio的“视图”菜单将其显示。然后,您将能够看到正在发生的事情并自行解决。

答案 5 :(得分:1)

e.Source是图像类型的对象。

因此您需要将发件人转换为边框。

边界b =发件人为边境;