2012-10-26 34 views
2

我正在做一個溫度轉換器作爲測試項目。它有三個應該相互溝通的上/下控制。 (右邊的標籤僅用於調試。)當我通過旋轉(例如攝氏度)更改溫度時,其相應標籤會正確更新,但我也希望Kelvin和華氏溫度值同時更改。但他們沒有。爲什麼不?如何使輸入控件在MVVM(WPF)中相互通信?

其意圖是模型(TempModel)只應保留一個值(開爾文)。其他應在需要時計算。我嘗試了不同的方法來獲取攝氏和華氏值。在這種情況下,我有模型中的屬性從私有_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; 
      } 
     } 

    } 
} 

回答

1

在setter方法FahrenheitCelsius設置Kelvin屬性而不是_kelvin字段。此外,請從Kelvin的設置者中提高所有三個屬性更改,而不是每個其他度量的設置者。這樣,當任何溫度變化時,Kelvin都會更新並通知視圖所有三個值都已更改。

此外,我假設您正在實施INotifyPropertyChanged,即使它沒有在您的代碼中指定在您的模型或視圖模型。

+0

'公共類TempModel:INotifyPropertyChanged'和下面的@blindmeis答案的組合使它工作。謝謝! – junior

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> 
+0

謝謝!這與@mlorbetske提到的接口(公共類TempModel:INotifyPropertyChanged)的實現一起工作良好。 – junior