I’m working on a temperature converter as a test project. It has three up/down-controls that should communicate with each other. (The labels to the right are only for debugging.) When I change the temperatures by spinning (e.g. Celsius) its corresponding label updates correctly, but I also want the Kelvin and Fahrenheit values to change simultaneously. But they don’t. Why not?
The intention is that the model (TempModel) only should keep one value (Kelvin). The others should be calculated when needed. I have tried different approaches to get the Celsius and Fahrenheit values. In this case I have properties in the model that calculates its value from the private _Kelvin variable. It works at start up, but not when I am changing the values in runtime.
I have also tried to do similar things with the properties in the view model.
I believe the solution is fairly simple and has something to do with the bindings, but I still can’t find it.
Here is what it looks like:
User interface image
Here is the view XAML code:
<Window x:Class="Temperature.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
Title="Temperature converter" Height="183" Width="468">
<Grid VerticalAlignment="Stretch">
<Label Content="Kelvin" Height="28" HorizontalAlignment="Left" Margin="10,10,0,0" Name="label1" VerticalAlignment="Top" />
<extToolkit:DoubleUpDown Name="_KelvinUD" Increment="0.1" FormatString="F2" Value="{Binding Kelvin}" HorizontalAlignment="Left" Width="100" VerticalAlignment="Top" Margin="113,14,0,0" />
<Label Height="28" HorizontalAlignment="Left" Margin="279,10,0,0" Name="label4" VerticalAlignment="Top" Content="{Binding Kelvin}" />
<Label Content="Celsius" Height="28" HorizontalAlignment="Left" Margin="12,44,0,0" Name="label2" VerticalAlignment="Top" />
<extToolkit:DoubleUpDown Name="_CelsiusUD" Increment="0.1" FormatString="F2" Value="{Binding Celsius}" HorizontalAlignment="Left" Width="100" VerticalAlignment="Top" Margin="113,48,0,0" />
<Label Height="28" HorizontalAlignment="Left" Margin="279,44,0,0" Name="label5" VerticalAlignment="Top" Content="{Binding Celsius}" />
<Label Content="Fahrenheit" Height="28" HorizontalAlignment="Left" Margin="12,78,0,0" Name="label3" VerticalAlignment="Top" />
<extToolkit:DoubleUpDown Name="_FarenheitUD" Increment="0.1" FormatString="F2" Value="{Binding Fahrenheit}" HorizontalAlignment="Left" Width="100" VerticalAlignment="Top" Margin="113,82,0,0" />
<Label Height="28" HorizontalAlignment="Left" Margin="279,78,0,0" Name="label6" VerticalAlignment="Top" Content="{Binding Fahrenheit}" />
</Grid>
The code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Temperature
{
public partial class MainWindow : Window
{
private TempViewModel _viewModel = new TempViewModel();
TempViewModel ViewModel
{
get { return _viewModel; }
}
public MainWindow()
{
InitializeComponent();
base.DataContext = ViewModel;
}
}
}
The model:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Temperature
{
public class TempModel
{
private double _kelvin;
public double Kelvin
{
get
{
return _kelvin;
}
set
{
_kelvin = value;
OnPropertyChanged("Kelvin");
}
}
public double Celsius
{
get
{
return _kelvin - 273.15;
}
set
{
_kelvin = value + 273.15;
OnPropertyChanged("Celsius");
}
}
public double Fahrenheit
{
get
{
return 9.0 / 5.0 * (_kelvin - 273.15) + 32;
}
set
{
_kelvin = 5.0 / 9.0 * (value - 32) + 273.15;
OnPropertyChanged("Fahrenheit");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
The view model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Temperature
{
class TempViewModel
{
TempModel _tempModel;
public TempViewModel()
{
_tempModel = new TempModel
{
Kelvin = 300.15 // Initial value
};
}
public TempModel TempModel
{
get
{
return _tempModel;
}
set
{
_tempModel = value;
}
}
public double Kelvin
{
get
{
return _tempModel.Kelvin;
}
set
{
_tempModel.Kelvin = value;
}
}
public double Celsius
{
get
{
return _tempModel.Celsius;
}
set
{
_tempModel.Celsius = value;
}
}
public double Fahrenheit
{
get
{
return _tempModel.Fahrenheit;
}
set
{
_tempModel.Fahrenheit = value;
}
}
}
}
In the setters for
FahrenheitandCelsiusset theKelvinproperty instead of the_kelvinfield. Also, raise all three property changes from the setter ofKelvininstead of the setter of each other measure. That way, when any temperature changes,Kelvinis updated and informs the view that all three values have changed.Also, I’m assuming you’re implementing
INotifyPropertyChangedeven though it wasn’t specified in your code on either your model or view model.