UWP 应用程序未更新视图
UWP app not updating view
一个简单的练习:在 UWP 应用的文本块中显示当前时间。
我正在使用 MVVMlight 和 PropertyChanged.Fody.
作为这个例子的基础,我使用这个 article and the MVVMlight / Fody implementation from here: Article 2
我有一个 MainViewModel。在这里,我正在创建 DateTimeModel class 的一个实例,如果引发 属性 更改事件(工作),我已经添加了调试输出。
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 class,我在其中使用 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 没有更新,而正在引发 属性Changed 事件。
我在这里缺少什么?
编辑:如果我使用 CurrentDateTime 作为标准 属性:
public DateTime CurrentDateTime { get; set; }
并在绑定起作用的构造函数中分配当前 DateTime。
CurrentDateTime = System.DateTime.Now;
每当引发 DateTimeModel
的 PropertyChanged
事件时,引发绑定到 MainViewModel
的 CurrentDateTime
的 PropertyChanged
事件:
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
class:
public DateTimeModel DateTimeModel { get; private set; }
...并直接绑定到 DateTimeModel
的 CurrentDateTime
属性:
<TextBlock Text="{Binding DateTimeModel.CurrentDateTime}"/>
您面临的问题是 MainViewModel.CurrentDateTime
仅在您分配 MainViewModel.DateTimeModel
时收到通知,而不是在 DateTimeModel
的属性更改时收到通知。
This is a known Fody limitation and a guy here found a walkaround 允许您通知 sub属性 更改,如下所示:
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}"/>
这需要按照 的建议将 DateTimeModel
更改为 属性:
public DateTimeModel DateTimeModel { get; }
一个简单的练习:在 UWP 应用的文本块中显示当前时间。 我正在使用 MVVMlight 和 PropertyChanged.Fody.
作为这个例子的基础,我使用这个
我有一个 MainViewModel。在这里,我正在创建 DateTimeModel class 的一个实例,如果引发 属性 更改事件(工作),我已经添加了调试输出。
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 class,我在其中使用 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 没有更新,而正在引发 属性Changed 事件。 我在这里缺少什么?
编辑:如果我使用 CurrentDateTime 作为标准 属性:
public DateTime CurrentDateTime { get; set; }
并在绑定起作用的构造函数中分配当前 DateTime。
CurrentDateTime = System.DateTime.Now;
每当引发 DateTimeModel
的 PropertyChanged
事件时,引发绑定到 MainViewModel
的 CurrentDateTime
的 PropertyChanged
事件:
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
class:
public DateTimeModel DateTimeModel { get; private set; }
...并直接绑定到 DateTimeModel
的 CurrentDateTime
属性:
<TextBlock Text="{Binding DateTimeModel.CurrentDateTime}"/>
您面临的问题是 MainViewModel.CurrentDateTime
仅在您分配 MainViewModel.DateTimeModel
时收到通知,而不是在 DateTimeModel
的属性更改时收到通知。
This is a known Fody limitation and a guy here found a walkaround 允许您通知 sub属性 更改,如下所示:
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}"/>
这需要按照 DateTimeModel
更改为 属性:
public DateTimeModel DateTimeModel { get; }