I'm currently developing a C# WPF app an encountered a very weird error. I shifted from working with several windows to working with UserControls and experience one very odd behaviour. I got a UserControl called DataEntryControl
, which has a ComboBox with SelectionChanged trigger in it, the XAML looking like this:
<StackPanel Grid.Row="1" Grid.Column="3" VerticalAlignment="Center">
<ComboBox Name="cbEntry" Width="200" HorizontalAlignment="Left" SelectionChanged="cbEntry_SelectionChanged">
<ComboBoxItem Content="Auto - Benziner" IsSelected="True" />
<ComboBoxItem Content="Auto - Diesel" />
<ComboBoxItem Content="Auto - Hybrid" />
<ComboBoxItem Content="Auto - Elektro" />
<ComboBoxItem Content="ÖPNV" />
<ComboBoxItem Content="Fahrrad" />
<ComboBoxItem Content="E-Bike" />
<ComboBoxItem Content="Homeoffice" />
</ComboBox>
</StackPanel>
The C#-Code for the DataEntryControl looks like this (excerpt):
public partial class DataEntryControl : UserControl
{
Benutzer currentUser = MainWindow.currentUser;
DBContext db = new DBContext();
public DataEntryControl()
{
InitializeComponent();
}
private void cbEntry_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (currentUser == null) return;
double saved = (db.Anreisetypen.Find(currentUser.AnreisetypenID).co2ProKm * currentUser.distanz -
db.Anreisetypen.Find(MainWindow.fahrzeugID((cbEntry.SelectedItem as ComboBoxItem).Content.ToString())).co2ProKm * currentUser.distanz);
tbSaved.Text = "Dadurch gespart:\n" + saved.ToString() + "g CO2";
tbTotal.Text = "Einsparung gesamt:\n" + (currentUser.ersparnis + saved).ToString() + "g CO2";
}
}
The Control is created when a user clicks a button in the MainWindow but here I encountered two very weird behaviours depending on how I activate the UserControl.
Version 1:
public void dataEntryClick(object sender, RoutedEventArgs e)
{
ControlGrid.Children.Clear();
ControlGrid.Children.Add(new DataEntryControl());
}
This causes the the cbEntry_SelectionChanged
method to get called instantly when the control is created, throwing a NullPointerException for tbSaved
and tbTotal
(two TextBoxes). I wonder how can this happen? How can an event trigger get triggered if the belonging XAML has not been loaded yet??
After this I figured that I can just check if those objects are null, this removes the error however the Text isn't set for these two textboxes which is annoying. I can work around this by emulating a click after ignoring the first firing of the event tho, I'm just curious.
Another thing I tried is creating the DataEntryControl
instance way before it get's loaded (when creating the MainWindow
instance), making my C#-Code in the MainWindow look like this:
Version 2:
public partial class MainWindow: Window {
DataEntryControl d { get; set; } = new DataEntryControl();
//... constructor and stuff
public void dataEntryClick(object sender, RoutedEventArgs e)
{
ControlGrid.Children.Clear();
ControlGrid.Children.Add(d);
}
}
This however causes the cbEntry_SelectionChanged
to never get triggered. It doesn't get triggered when initializing (which is good) but also doesn't get triggered when changing the selection, which is weird since it listens to the SelectionChanged event.
As I prevsiouly wrote: I built a not-so-nice workaround for this problem by just aborting the selection function if either the ComboBox or the TextBoxes are null - this leaves me with 99% of the functionality I want to achieve but imo doesn't make a lot of sense, hence I still want to know why WPF behaves like this in this situation. I also did not encounter this problem when I used a DataEntryWindow
instead of a DataEntryControl
, which makes it even weirder. I hope somebody can help me with this, thanks!