2012-05-01 25 views
2

現在、WP7のTimePickerに問題があります。特に、ViewModelにバインドしています。問題のTimePickerは、アラームの時刻を設定します。ページが最初にロードされると、TimePickerはAlarmオブジェクトの値を正しく表示します(この場合、デフォルト値は午前12時です)。ただし、ユーザーが新しい値を選択した場合、モデルには反映されません。前の値の12:00に上書きされます。WP7:TimePickerバインディングが新しい値で更新されない

MVVMを使用してこのフォームを作成し、データバインディングを保持しています。特に私が間違っていることは何ですか?

[DataContract] 
public class Alarm : INotifyPropertyChanged 
{ 
    private bool _active; 
    private DateTime _time; 

    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public DateTime Time 
    { 
     get 
     { 
      return _time; 
     } 
     set 
     { 
      if (_time != value) 
      { 
       _time = value; 
       RaisePropertyChanged("Time"); 
      } 
     } 
    } 

    [DataMember] 
    public AlarmFrequency Frequency { get; set; } 

    [DataMember] 
    public AlarmTone Tone { get; set; } 

    [DataMember] 
    public bool Active { 
     get { 
      return _active; 
     } 
     set { 
      _active = value; 
     } 
    } 

    public string AlarmTimeString { 
     get { 
      return Time.ToShortTimeString(); 
     } 
    } 



    /** 
    * Default Constructor 
    */ 
    public Alarm() 
    { 
     Debug.WriteLine("Alarm: Using default constructor"); 
     this.Name = "New Alarm"; 
     this.Time = DateTime.Today; 
     this.Frequency = new AlarmFrequency(); 
     this.Tone = new AlarmTone(); 
     this.Active = true; 

     Debug.WriteLine("Alarm hours is " + this.Time.Hour); 
    } 

    /** 
    * Parameterised constructor 
    */ 
    public Alarm(string Name, DateTime Time, AlarmFrequency Frequency, 
        AlarmTone Tone, bool Active) 
    { 
     Debug.WriteLine("Alarm: Using parameterised constructor"); 
     this.Name = Name; 
     this.Time = Time; 
     this.Frequency = Frequency; 
     this.Tone = Tone; 
     this.Active = Active; 
     } 
} 
Alarm.cs

(ビュー)AlarmEditorControl.xaml

<TextBlock Height="30" HorizontalAlignment="Left" Margin="1,6,0,0" Name="lblAlarmTime" Text="Alarm Time:" VerticalAlignment="Top" Grid.Column="2" FontSize="26" /> 
<!-- Data binding isn't working for updates! --> 
<toolkit:TimePicker HorizontalAlignment="Left" Margin="140,34,0,0" Name="tpAlarmTime" VerticalAlignment="Top" Width="161" Grid.Column="1" Grid.ColumnSpan="2" Value="{Binding Path=Time, Mode=TwoWay}" /> 

(ViewModelに)AlarmEditorModel.cs

[DataContractAttribute] 
public class AlarmEditorModel 
{ 
    private int _index; 

    [DataMemberAttribute] 
    public Alarm Alarm { get; set; } 

    [DataMemberAttribute] 
    public int Index 
    { 
     get 
     { 
      return _index; 
     } 

     set 
     { 
      _index = value; 
     } 
    } 

    public AlarmEditorModel(int index) 
    { 
     _index = index; 
     Alarm = new Alarm(); 

     // Get the list of alarms 
     AlarmSerializer serializer = new AlarmSerializer(); 

     // Check the index is in range 
     List<Alarm> alarms = serializer.AlarmList; 
     if (_index > -1 && index < alarms.Count) 
     { 
      Alarm = alarms[_index]; 
     } 
    } 

    public void Commit() 
    { 
     // Get the current list of alarms 
     AlarmSerializer serializer = new AlarmSerializer(); 
     List<Alarm> alarms = serializer.AlarmList; 

     // Replace our new value 
     alarms[_index] = Alarm; 
     serializer.AlarmList = alarms; 
    } 
} 

(モデル)

(ページを呼び出す)NewAlarm.xaml.cs

private List<Channel> feeds; 
    private AlarmEditorModel _aem; 
    private int _index; 

    public NewAlarm() 
    { 
     InitializeComponent(); 

     feeds = new List<Channel>(); 
     feeds.Add(new Channel(null, null, "Feed 1", DateTime.Now)); 
     feeds.Add(new Channel(null, null, "Feed 2", DateTime.Now)); 
    } 

    /** 
    * Setup functions when the page is loaded 
    */ 
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
    { 
     // Function vars + debug 

     Debug.WriteLine("Navigating to"); 

     // Check if we're recovering from tombstone 
     if (!StateUtilities.IsLaunching && this.State.ContainsKey("AlarmState")) 
     { 
      // Recover the saved model 
      _aem = (AlarmEditorModel)this.State["AlarmState"]; 
     } 
     else 
     { 
      try 
      { 
       // Editing an alarm. 
       _index = Convert.ToInt32(this.NavigationContext.QueryString["index"]); 
       Debug.WriteLine("Editing an alarm"); 
      } 
      catch (KeyNotFoundException knfe) 
      { 
       Debug.WriteLine(knfe.Message); 

       // No index provided, new alarm 
       _index = -1; 
      } 

      // Set the model from the index 
      _aem = new AlarmEditorModel(_index); 
     } 

     AlarmEditor.DataContext = _aem.Alarm; 
     Debug.WriteLine(_aem.Alarm.Time.Hour); 
    } 

    /** 
    * Preserve alarm details when tombstoning 
    */ 
    protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e) 
    { 
     base.OnNavigatedFrom(e); 

     if (this.State.ContainsKey("AlarmState")) 
     { 
      this.State["AlarmState"] = _aem; 
     } 
     else 
     { 
      this.State.Add("AlarmState", _aem); 
     } 

     StateUtilities.IsLaunching = false; 
    } 

EDIT 1

Alarm.Timeのsetterは二回呼び出されていると思われます。 9:10までの時間を設定するとき

[DataMember] 
    public DateTime Time 
    { 
     get 
     { 
      return _time; 
     } 
     set 
     { 
      Debug.WriteLine("Current time is " + _time.ToShortTimeString()); 
      Debug.WriteLine("New time is " + value.ToShortTimeString()); 

      if (_time != value) 
      { 
       Debug.WriteLine("Changing time value"); 
       _time = value; 
       RaisePropertyChanged("Time"); 
      } 
     } 
    } 

次の出力がログに生成されます:時間プロパティに次のデバッグ行を追加することにより

Current time is 4:00 AM 
New time is 9:10 AM 
Changing time value 
Current time is 12:00 AM 
New time is 4:00 AM 
Changing time value 
+1

ViewModelとDataContextはどちらが不明ですか。 – Robaticus

+1

AlarmEditorModel.csはViewModelであり、そのインスタンスはDataContextとしてAlarmEditorControl(View)のインスタンスに渡されます。 –

+1

愚かな質問ですが、この行では値が異なります:if(_time!= value)? –

答えて

1

問題は、私は考えて解決しました。私はそれがViewModelにで上書きされる前にTimePickerの値を取得するために墓碑から回復するときOnNavigatedToに追加のチェックを行うために必要な:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) 
{ 
     // Check if we're recovering from tombstone 
     if (!StateUtilities.IsLaunching && this.State.ContainsKey("AlarmState")) 
     { 
      // Recover the saved model 
      _aem = (AlarmEditorModel)this.State["AlarmState"]; 

      // Use the value from the TimePicker 
      _aem.Alarm.Time = (DateTime)AlarmEditor.tpAlarmTime.Value; 
     } 
     else 
     ... 

は、このソリューションには、いくつかのより多くのテストを行う必要がありますが、それは今のところ仕事をしているようだ。

関連する問題