2017-09-13 6 views
0

簡単なエクササイズ:UWPアプリのテキストブロックに現在の時間を表示します。 私はMVVMlightとPropertyChanged.Fodyを使用しています。UWPアプリがビューを更新しない

この例のためのベースとして、私はここからこのArticle 1記事及びMVVMlight/Fodyの実装を使用しています:Article 2

私はMainViewModelを持っています。ここでは、DateTimeModelクラスのインスタンスを作成しています。プロパティ変更イベントが発生した(動作中)場合は、すでにDebug出力を追加しています。

using System.Diagnostics; 
 
using GalaSoft.MvvmLight; 
 
using Logic.Ui.Models.DateTime; 
 
using PropertyChanged; 
 

 
namespace Logic.Ui 
 
{ 
 
    public class MainViewModel : ViewModelBase, INotifyPropertyChanged 
 
    { 
 

 
     public DateTimeModel DateTimeModel; 
 

 
     [DependsOn(nameof(DateTimeModel))] 
 
     public DateTime CurrentDateTime => DateTimeModel.CurrentDateTime; 
 

 
     public MainViewModel() 
 
     { 
 
      DateTimeModel = new DateTimeModel(); 
 

 
      DateTimeModel.PropertyChanged += (s, e) => 
 
      { 
 
       Debug.WriteLine("DateTime PropertyChanged"); 
 
      }; 
 
     } 
 

 
     #region Events 
 

 
     public event PropertyChangedEventHandler PropertyChanged; 
 

 
     #endregion 
 

 
    } 
 
}

そして、私はThreadPoolTimerを使用してタイムを更新DateTimeModelクラス:

using System; 
 
using System.ComponentModel; 
 
using System.Diagnostics; 
 
using Windows.System.Threading; 
 
using Windows.UI.Core; 
 

 
namespace Logic.Ui.Models.DateTime 
 
{ 
 

 
    public class DateTimeModel : INotifyPropertyChanged 
 
    { 
 
     private ThreadPoolTimer _clockTimer; 
 

 
     public System.DateTime CurrentDateTime { get; set; } 
 
     
 
     public DateTimeModel() 
 
     { 
 
      _clockTimer = ThreadPoolTimer.CreatePeriodicTimer(ClockTimerTickAsync, TimeSpan.FromMilliseconds(1000)); 
 
     } 
 

 
     private async void ClockTimerTickAsync(ThreadPoolTimer timer) 
 
     { 
 
      await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
 
      { 
 
       CurrentDateTime = System.DateTime.Now; 
 
       Debug.WriteLine("Time updated"); 
 
      }); 
 

 
     } 
 

 
     #region Events 
 

 
     public event PropertyChangedEventHandler PropertyChanged; 
 

 
     #endregion 
 
    } 
 
}

XAMLコードは次のようになります

<Page 
 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 
    xmlns:local="using:MirrorV2.Ui.Raspberry" 
 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 
    x:Class="MirrorV2.Ui.Raspberry.MainPage" 
 
    mc:Ignorable="d" 
 
    DataContext="{Binding Main, Source={StaticResource Locator}}"> 
 

 
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
 

 
     <TextBlock Text="{Binding CurrentDateTime}"/> 
 
     
 
    </Grid> 
 
</Page>

ここでの問題は、のPropertyChangedイベントが発生beeingている間、UIは、更新されないということです。 私はここで何が欠けていますか?

EDIT:

public DateTime CurrentDateTime { get; set; } 

をし、コンストラクタで結合作品を現在のDateTimeを割り当てる:私は、標準のプロパティとしてCurrentDateTimeを使用していた場合。

public class MainViewModel : ViewModelBase, INotifyPropertyChanged 
{ 
    public DateTimeModel DateTimeModel; 

    [DependsOn(nameof(DateTimeModel))] 
    public DateTime CurrentDateTime => DateTimeModel.CurrentDateTime; 

    public MainViewModel() 
    { 
     DateTimeModel = new DateTimeModel(); 

     DateTimeModel.PropertyChanged += (s, e) => 
     { 
      Debug.WriteLine("DateTime PropertyChanged"); 
      this.RaisePropertyChanged(nameof(CurrentDateTime)); //<--- 
     }; 
    } 

    #region Events 
    public event PropertyChangedEventHandler PropertyChanged; 
    #endregion 
} 

それともDateTimeModelでしMainViewModelクラスのプロパティ:

CurrentDateTime = System.DateTime.Now; 

答えて

2

問題がMainViewModel.CurrentDateTimeであるだけに通知されます。

This is a known Fody limitation、あなたはそうのようなサブプロパティの変更に通知することを可能にする男here found a walkaround

public class MainViewModel : ViewModelBase, INotifyPropertyChanged 
{ 

    // ... snip ... 

    [DependsOn(nameof(DateTimeModel))] 
    [DependsOn("DateTimeModel.CurrentDateTime")] 
    public DateTime CurrentDateTime => DateTimeModel.CurrentDateTime; 
} 

しかし、私はそれが直接MainViewModel.DateTimeModel

<TextBlock Text="{Binding DateTimeModel.CurrentDateTime}"/> 

MainViewModel.CurrentDateTimeとバインドを削除するにははるかにエレガントだと思いますこれはmm8のようにプロパティをDateTimeModelに変更する必要があります。

public DateTimeModel DateTimeModel { get; } 
+0

私はダイレクトバインディングを使用しました。これは私にとって最もエレガントな方法です。ありがとう。 – Christoph

1

DateTimeModelPropertyChangedイベントが発生するたびに、あなたがバインドMainViewModelCurrentDateTimeためPropertyChangedイベントを上げる

public DateTimeModel DateTimeModel { get; private set; } 

...そして直接のプロパティ:DateTimeModelのプロパティを変更するときは、MainViewModel.DateTimeModelない割り当てるときに、あなたが直面している

<TextBlock Text="{Binding DateTimeModel.CurrentDateTime}"/> 
関連する問題