UWP应用程序不更新视图

时间:2017-09-13 18:00:51

标签: c# uwp mvvm-light fody-propertychanged

一个简单的练习:在UWP应用程序的Textblock中显示当前时间。 我正在使用MVVMlight和PropertyChanged.Fody。

作为此示例的基础,我在此处使用此Article 1文章和MVVMlight / Fody实现:Article 2

我有一个MainViewModel。在这里,我创建了DateTimeModel类的实例,如果引发了属性更改事件(工作),我已经添加了一个Debug输出。



ActiveSheet




一个DateTimeModel类,我使用ThreadPoolTimer更新时间:



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

    }
}




XAML代码如下所示:



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
    }
}




这里的问题是UI没有更新,而propertyChanged事件正在被提升。 我在这里失踪了什么?

编辑:如果我使用CurrentDateTime作为标准属性:

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

并在构造函数中指定绑定的当前DateTime。

public DateTime CurrentDateTime { get; set; }

2 个答案:

答案 0 :(得分:2)

您面临的问题MainViewModel.CurrentDateTime只有在您分配MainViewModel.DateTimeModel时才会收到通知,而不会在DateTimeModel的属性发生变化时收到通知。

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.CurrentDateTime并直接绑定到MainViewModel.DateTimeModel会更优雅

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

这需要按照mm8

的建议将DateTimeModel更改为属性
public DateTimeModel DateTimeModel { get; }

答案 1 :(得分:1)

每当PropertyChanged引发CurrentDateTime事件时,提升您绑定的MainViewModel PropertyChanged的{​​{1}}事件:

DateTimeModel

或者您可以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属性:

public DateTimeModel DateTimeModel { get; private set; }

...并直接绑定到CurrentDateTime的{​​{1}}属性:

DateTimeModel