0

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

作为这个例子的基础,我使用这篇文章 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

    }
}

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

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>

这里的问题是 UI 没有更新,而 propertyChanged 事件正在引发。我在这里缺少什么?

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

public DateTime CurrentDateTime { get; set; }

并在构造函数中分配当前 DateTime 绑定有效。

CurrentDateTime = System.DateTime.Now;
4

2 回答 2

2

您面临的问题是MainViewModel.CurrentDateTime仅在您分配时收到通知MainViewModel.DateTimeModel,而不是在DateTimeModel属性更改时收到通知。

这是一个已知的 Fody 限制,这里的一个人发现了一个解决方法,允许您通知子属性更改,如下所示:

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

这需要更改DateTimeModelmm8建议的属性:

public DateTimeModel DateTimeModel { get; }
于 2017-09-13T19:28:06.133 回答
1

每当引发的PropertyChanged事件CurrentDateTime时,引发MainViewModel您绑定到的 的PropertyChanged事件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属性DateTimeModel

<TextBlock Text="{Binding DateTimeModel.CurrentDateTime}"/>
于 2017-09-13T18:57:06.750 回答