Reputation: 377
Here's my entire code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void sldChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
double red, green, blue;
red = sldRed.Value;
green = sldGreen.Value;
blue = sldBlue.Value;
changeColors(red, green, blue);
}
private void inputChanged(object sender, TextChangedEventArgs e)
{
double red, green, blue;
red = Convert.ToDouble(txtRed.Text);
green = Convert.ToDouble(txtGreen.Text);
blue = Convert.ToDouble(txtBlue.Text);
sldRed.Value = red;
sldGreen.Value = green;
sldBlue.Value = blue;
changeColors(red, green, blue);
}
void changeColors(double red, double green, double blue)
{
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
txtRed.Text = Convert.ToString(sldRed.Value);
txtGreen.Text = Convert.ToString(sldGreen.Value);
txtBlue.Text = Convert.ToString(sldBlue.Value);
}
}
and here's my entire .xaml code.
<Grid x:Name="frmGrid" Margin="0,0,2,0">
<Slider x:Name="sldRed" HorizontalAlignment="Left" Margin="57,10,0,0" VerticalAlignment="Top" Width="757" ValueChanged="sldChanged" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True" SmallChange="1" Value="1"/>
<Slider x:Name="sldBlue" HorizontalAlignment="Left" Margin="57,76,0,0" VerticalAlignment="Top" Width="757" ValueChanged="sldChanged" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True" SmallChange="1" Value="1"/>
<Slider x:Name="sldGreen" HorizontalAlignment="Left" Margin="57,45,0,0" VerticalAlignment="Top" Width="757" ValueChanged="sldChanged" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True" SmallChange="1" Value="1"/>
<Label Content="Red" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<Label Content="Blue" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top"/>
<Label Content="Green" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtRed" HorizontalAlignment="Left" Height="23" Margin="819,9,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="41" TextChanged="inputChanged"/>
<TextBox x:Name="txtBlue" HorizontalAlignment="Left" Height="23" Margin="819,74,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="41" TextChanged="inputChanged"/>
<TextBox x:Name="txtGreen" HorizontalAlignment="Left" Height="23" Margin="819,41,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="41" TextChanged="inputChanged" Text="1"/>
</Grid>
You can see I've assigned a value to those textboxes for testing purposes.
For some reason I keep getting this error
Which refers to these two lines.
green = Convert.ToDouble(txtGreen.Text);
blue = Convert.ToDouble(txtBlue.Text);
Note how the similar line above it works perfectly
red = Convert.ToDouble(txtRed.Text);
I'm not that experienced in C# yet, nor am I experienced in reading errors like those. If you have any idea as to why I'm getting this error and maybe provide me with a possible solution, it would be greatly appreciated.
PS: Something I just thought might be of use to you, I get this error before the program even starts up.
Here's 2 screenshots where 1 doesn't load at all, while the 2nd loads perfectly & works.
Upvotes: 0
Views: 718
Reputation: 4563
The reason why this is failing is because the valuechanged event gets called when you initially create the slider in xaml and include this: Value="1". The event gets raised before the other controls are created, and thus the null exception.
WPF is built heavily upon the concept of binding, and you should utilize it as much as possible because it will make your life a lot easier. I altered your code to show you how to do it using bindings.
xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
x:Name="TheMainWindow">
<Grid x:Name="frmGrid" Margin="0,0,2,0">
<Slider x:Name="sldRed" HorizontalAlignment="Left" Margin="57,10,0,0" VerticalAlignment="Top" Width="757" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True"
SmallChange="1" Value="{Binding Path=Red, ElementName=TheMainWindow, Mode=TwoWay}"/>
<Slider x:Name="sldBlue" HorizontalAlignment="Left" Margin="57,76,0,0" VerticalAlignment="Top" Width="757" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True"
SmallChange="1" Value="{Binding Path=Blue, ElementName=TheMainWindow, Mode=TwoWay}"/>
<Slider x:Name="sldGreen" HorizontalAlignment="Left" Margin="57,45,0,0" VerticalAlignment="Top" Width="757" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True"
SmallChange="1" Value="{Binding Path=Green, ElementName=TheMainWindow, Mode=TwoWay}"/>
<Label Content="Red" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<Label Content="Blue" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top"/>
<Label Content="Green" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtRed" HorizontalAlignment="Left" Height="23" Margin="819,9,0,0" TextWrapping="Wrap" Text="{Binding Path=Red, ElementName=TheMainWindow}" VerticalAlignment="Top" Width="41"/>
<TextBox x:Name="txtBlue" HorizontalAlignment="Left" Height="23" Margin="819,74,0,0" TextWrapping="Wrap" Text="{Binding Path=Blue, ElementName=TheMainWindow}" VerticalAlignment="Top" Width="41" />
<TextBox x:Name="txtGreen" HorizontalAlignment="Left" Height="23" Margin="819,41,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding Path=Green, ElementName=TheMainWindow}" Width="41" />
</Grid>
</Window>
code
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
}
private double _red = 1;
public double Red
{
get { return _red; }
set
{
_red = value;
OnPropertyChanged("Red");
}
}
private double _green = 1;
public double Green
{
get { return _green; }
set
{
_green = value;
OnPropertyChanged("Green");
}
}
private double _blue = 1;
public double Blue
{
get { return _blue; }
set
{
_blue = value;
OnPropertyChanged("Blue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Upvotes: 0
Reputation: 534
I think the problem is with your Window_Loaded_1
it changes the text value of the text boxes causing the inputChanged
method to be called. try commenting out the code in Window_Loaded_1
and see if the exception still happens.
One way to solve this problem is to use binding to wire together the values of the sliders and the text boxes. Your xaml should look like this:
<Grid x:Name="frmGrid" Margin="0,0,2,0">
<Slider x:Name="sldRed" HorizontalAlignment="Left" Margin="57,10,0,0" VerticalAlignment="Top" Width="757" ValueChanged="sldChanged" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True" SmallChange="1" Value="1"/>
<Slider x:Name="sldBlue" HorizontalAlignment="Left" Margin="57,76,0,0" VerticalAlignment="Top" Width="757" ValueChanged="sldChanged" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True" SmallChange="1" Value="1"/>
<Slider x:Name="sldGreen" HorizontalAlignment="Left" Margin="57,45,0,0" VerticalAlignment="Top" Width="757" ValueChanged="sldChanged" ClipToBounds="True" Maximum="255" TickPlacement="BottomRight" IsSnapToTickEnabled="True" SmallChange="1" Value="1"/>
<Label Content="Red" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
<Label Content="Blue" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top"/>
<Label Content="Green" HorizontalAlignment="Left" Margin="10,41,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="txtRed" HorizontalAlignment="Left" Height="23" Margin="819,9,0,0" TextWrapping="Wrap" Text="{Binding ElementName=sldRed, Path=Value, Mode=TwoWay}" VerticalAlignment="Top" Width="41"/>
<TextBox x:Name="txtBlue" HorizontalAlignment="Left" Height="23" Margin="819,74,0,0" TextWrapping="Wrap" Text="{Binding ElementName=sldBlue, Path=Value, Mode=TwoWay}" VerticalAlignment="Top" Width="41"/>
<TextBox x:Name="txtGreen" HorizontalAlignment="Left" Height="23" Margin="819,41,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="41" Text="{Binding ElementName=sldGreen, Path=Value, Mode=TwoWay}"/>
</Grid>
and your code should look like this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void sldChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
red = sldRed.Value;
green = sldGreen.Value;
blue = sldBlue.Value;
changeColors(red, green, blue);
}
void changeColors(double red, double green, double blue)
{
}
}
You can get rid of inputChanged
and respond only to the slider changes
Upvotes: 0
Reputation: 835
The event handler fires when the input changes. If you hit backspace in any one of the boxes your Text is now an empty string or null. You can't turn those into doubles. Try Double.TryParse() instead of Convert.ToDouble() to determine if it's actually a parsable input like so:
private void inputChanged(object sender, TextChangedEventArgs e)
{
double red, green, blue;
if(Double.TryParse(txtRed.Text, out red) &&
Double.TryParse(txtGreen.Text, out green) &&
Double.TryParse(txtBlue.Text, out blue))
{
sldRed.Value = red;
sldGreen.Value = green;
sldBlue.Value = blue;
changeColors(red, green, blue);
}
}
If all the values in the RGB TextBoxes are valid the if statement will be true and red, green and blue will be set properly.
This is of course assuming that sldGreen and sldBlue are not null.
Upvotes: 0
Reputation: 28970
txtRed and txtBlue
does not contain value. but txtRed contains value
You can add validation script in order to ensure that yours controls are not empty
Upvotes: 2