我正在研究温度转换器作为测试项目。它有三个上/下控制,应该相互通信。 (右侧的标签仅用于调试。)当我通过旋转(例如摄氏度)更改温度时,其相应的标签会正确更新,但我也希望Kelvin和Fahrenheit值同时更改。但他们没有。为什么不呢?
意图是模型(TempModel)只应保留一个值(开尔文)。其他应在需要时计算。我尝试过不同的方法来获得Celsius和Fahrenheit值。在这种情况下,我在模型中具有从私有_Kelvin变量计算其值的属性。它在启动时工作,但在我在运行时更改值时却不行。
我还试图用视图模型中的属性做类似的事情。
我相信解决方案相当简单并且与绑定有关,但我仍然无法找到它。
以下是它的样子: User interface image
以下是XAML代码视图:
<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>
背后的代码:
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;
}
}
}
模特:
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));
}
}
}
}
视图模型:
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;
}
}
}
}
答案 0 :(得分:1)
在Fahrenheit
和Celsius
的设置中设置Kelvin
属性而不是_kelvin
字段。此外,从Kelvin
的setter中提取所有三个属性更改,而不是每个其他度量的setter。这样,当任何温度发生变化时,Kelvin
会更新,并通知视图所有三个值都已更改。
此外,我假设您正在实施INotifyPropertyChanged
,即使您的模型或视图模型的代码中未指定它。
答案 1 :(得分:1)
如果一个属性的更改也会更改其他两个属性,则还必须为其他属性引发OnPropertyChanged以通知您的视图。
这应该工作(快速和肮脏的方法)。我只是暴露并绑定到模型属性。
public class TempModel
{
private double _kelvin;
public double Kelvin
{
get
{
return _kelvin;
}
set
{
_kelvin = value;
OnPropertyChanged("Kelvin");
OnPropertyChanged("Celsius");
OnPropertyChanged("Fahrenheit");
}
}
public double Celsius
{
get
{
return _kelvin - 273.15;
}
set
{
_kelvin = value + 273.15;
OnPropertyChanged("Celsius");
OnPropertyChanged("Kelvin");
OnPropertyChanged("Fahrenheit");
}
}
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");
OnPropertyChanged("Celsius");
OnPropertyChanged("Kelvin");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class TempViewModel
{
TempModel _tempModel;
public TempViewModel()
{
_tempModel = new TempModel
{
Kelvin = 300.15 // Initial value
};
}
public TempModel TempModel
{
get
{
return _tempModel;
}
set
{
_tempModel = value;
}
}
}
<Grid VerticalAlignment="Stretch">
<extToolkit:DoubleUpDown Increment="0.1" FormatString="F2" Value="{Binding TempModel.Kelvin}" HorizontalAlignment="Left" Width="100" VerticalAlignment="Top" Margin="113,14,0,0" />
<extToolkit:DoubleUpDown Increment="0.1" FormatString="F2" Value="{Binding TempModel.Celsius}" HorizontalAlignment="Left" Width="100" VerticalAlignment="Top" Margin="113,48,0,0" />
<extToolkit:DoubleUpDown Increment="0.1" FormatString="F2" Value="{Binding TempModel.Fahrenheit}" HorizontalAlignment="Left" Width="100" VerticalAlignment="Top" Margin="113,82,0,0" />
</Grid>