C # почему нуль после приведения - PullRequest
3 голосов
/ 14 июня 2011

Привет всем, пожалуйста, помогите мне, я так запутался, почему мой код имеет нулевое значение после приведения, это код 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")

, пожалуйста, помогите мне, почему это дает ноль?и как восстановить мою программу, чтобы можно было запустить.

Ответы [ 6 ]

15 голосов
/ 14 июня 2011

Очевидно, e.Source не относится к типу Border.

Первое, что вам нужно исправить, это ваш состав. Вы используете

Border b = e.Source as Border;

, который возвращает null, если e.Source не является границей, что приводит к последующему исключению NullReferenceException. Поскольку впоследствии вы не проверяете на ноль, вам следует использовать обычное приведение:

Border b = (Border)e.Source;

Это не решит проблему, лежащую в основе, но убедится, что

  • вы получите правильное исключение для основной проблемы (InvalidCastException вместо NullReferenceException) и
  • ошибка выдается в строке, которая действительно является причиной проблемы (а не в следующем if, который совершенно невиновен).

Теперь второе, источник вашей проблемы: RoutedEventsArgs.Source - это , а не граница, к которой вы прикрепили обработчик события (т. Е. Это не элемент управления , обрабатывающий событие ). Это элемент управления, который вызывает событие, которое, вероятно, является изображением внутри границы. Подробности смотрите в документации RoutedEventArgs.Source .

Таким образом, чтобы решить эту проблему, используйте отправителя вместо e.Source:

Border b = (Border)sender;
4 голосов
/ 14 июня 2011

Во-первых, вот как as ведет себя, когда приведение не удается.Это сделано таким образом, чтобы вы могли легко проверить, сделал ли он или нет.Если бы вы написали

Border b = (Border)e.Source;

, то получилось бы InvalidCastException.

Second, 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 #, вы наиболеескорее всего получит ошибку во время компиляции.

4 голосов
/ 14 июня 2011

Возможно, отправитель будет Border, попробуйте сначала разыграть отправителя как Границу:

  Border b = sender as Border;

Если это не поможет, просто установите точку останова в обработчике, чем откройте окно наблюдения, и вы увидите фактические типы sender и e.Source.

2 голосов
/ 14 июня 2011

Похоже, e.Source не является границей, поэтому e.Source как Border имеет значение null. Источником может быть другой объект внутри границы, причем событие направляется к границе.

Вы можете попробовать проверить тип e.Source с помощью

if (e.Source is Border)
{
}

или вы можете получить свой пограничный объект, применив отправителя вместо e.Source.

1 голос
/ 14 июня 2011

e.Source - объект типа image.

Так что вам нужно разыграть отправителя как Границу.

Граница b = отправитель как Граница;

1 голос
/ 14 июня 2011

Измените свой код, чтобы он выглядел так:

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. Тогда вы сможете увидеть, что происходит, и сами разобраться в этом.

...