Генерируется исключение типа
System.NullReferenceException: "Ссылка на объект не указывает на экземпляр объекта."
Вот такая у меня разметка XAML:
<Label x:Name="Label_Seconds" Content="0 секунд" HorizontalAlignment="Left" Margin="115,2,0,0" VerticalAlignment="Top" FontSize="16"/>
<Slider x:Name="Numbers_Slider" HorizontalAlignment="Left" Margin="10,33,0,0" VerticalAlignment="Top" Width="100" ValueChanged="Numbers_Slider_ValueChanged" Value="4" UseLayoutRounding="False" Minimum="4" Maximum="6"/>
<Label x:Name="Label_Numbers" Content="4 числа" HorizontalAlignment="Left" Margin="115,29,0,0" VerticalAlignment="Top" FontSize="16" RenderTransformOrigin="0.462,1.355"/>
<Slider x:Name="Seconds_Slider" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="100" ValueChanged="Seconds_Slider_ValueChanged" Value="4" UseLayoutRounding="False" Minimum="4" Maximum="6"/>
Вот код С#:
private void Numbers_Slider_ValueChanged( object sender, RoutedPropertyChangedEventArgs<double> e )
{
// Здесь Label_Numbers == null
Label_Numbers.Content = $"{Numbers_Slider.Value.ToInt32 ( )} числа";
}
private void Seconds_Slider_ValueChanged( object sender, RoutedPropertyChangedEventArgs<double> e )
{
Label_Seconds.Content = $"{Seconds_Slider.Value} секунды";
}
А теперь к вопросу. По задумке, должен меняться текст Label в зависимости от значения слайдера. Но не тут то было. При первом запуске было все нормально, но потом нарисовал второй такой слайдер и тут же выбрасывает исключение. Где проблема и почему все таки Label_Numbers = null
Лучше всего в вашем случае подписываться на события после того как все элементы уже точно инициализированы:
public MainWindow()
{
InitializeComponent();
Numbers_Slider.ValueChanged += Numbers_Slider_ValueChanged;
Seconds_Slider.ValueChanged += Seconds_Slider_ValueChanged;
}
А из разметки подписку убрать.
Дело в том, что интерпретатор XAML читает документ сверху вниз и при установке слайдеру свойства Value сразу срабатывает событие ValueChanged, но Label_Numbers здесь еще не существует, т.к. описан ниже, поэтому и возникает NRE.
Можно, конечно, поместить определение Label_Numbers в разметке выше Numbers_Slider, но это ненадежное решение.
А вообще, в WPF этот пример можно (и нужно) сделать вообще без подписки на события — с использованием механизма привязок. Также вам необходимо отказаться от "рисования контролов мышкой" и писать разметку вручную, активно используя панели компоновки (да, с ними надо ознакомиться, но их не много и знакомство с ними быстрое):
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="16"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="5,2.5,0,2.5"/>
</Style>
<Style TargetType="Slider">
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</Grid.Resources>
<Slider Name="Seconds_Slider" Value="4" Minimum="4" Maximum="6"/>
<TextBlock Grid.Column="1" Text="{Binding ElementName=Seconds_Slider, Path=Value, StringFormat={}{0:0.##} секунд}"/>
<Slider Grid.Row="1" Name="Numbers_Slider" Value="4" Minimum="4" Maximum="6"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding ElementName=Numbers_Slider, Path=Value, StringFormat={}{0:0.##} числа}"/>
</Grid>
Да, разметка вышла более громоздкая за счет выноса одинакового форматирования в стиль, но когда контролов станет гораздо больше, эта громоздкость нивелируется, также стили можно вынести в отдельный словарь ресурсов или в App.xaml. Вынос оформления в стиль разгружает основную разметку — в ней остается только то что существенно здесь и сейчас, оформление же получается тоже скомпонованным в одном месте.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости