我最初有一个异步MVVM模式;在调试中,我现在将其剥离为仅仅以下 - 同步 - 代码:
XAML:
<Grid x:Name="LayoutRoot">
<Button x:Name="button" Content="{Binding Path=bText, FallbackValue=Initial}" Tapped="onTap"/>
</Grid>
C#
public partial class VPage : Page
{
public ViewModel viewModel;
public VPage()
{
DataContext = viewModel = new ViewModel();
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e) { viewModel.onNavigatedTo(); }
private void onTap(object sender, TappedRoutedEventArgs eventArgs) { viewModel.onTap(); }
}
public class viewModel : INotifyPropertyChanged
{
private String _bText;
public String bText { get { return _bText; } set { _bText = value; DB.major("ViewModel: bText=" + _bText); NotifyPropertyChanged("bText"); } }
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged == null)
writeln("Null handler!");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));
}
public void onNavigatedTo() { bText = "Updated via onNavigatedTo"; }
private int count = 0;
public void onTap() { bText = "Updated via onTap " + count++.ToString(); }
}
现在是整个代码库 - 我已经删除了所有模型和异步代码以帮助调试。
启动时,Page构造函数会运行并完成。
随后,调用VPage.OnNavigatedTo,并调用ViewModel.onNavigatedTo();
在对OnNavigatedTo的调用中,writeln触发,表明处理程序为null,表明组件初始化没有以某种方式完成。随后 - 即onTap - 一切正常,处理程序就位。有趣的是,该字段更新为&#34;通过onNavigatedTo&#34;更新。即使null处理程序writeln被触发。
当我有完整的异步模式时,我认为这是一个线程问题,但现在显而易见的是它更简单了。
答案 0 :(得分:1)
我认为你没有足够的时间来注册其处理程序。快速解决方法就是屈服。试试这个:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
// This forces the rest of your code to enqueue after UI is done.
await Task.Yield();
viewModel.populate();
}
<强>更新强>
在您的页面位于可视树中之前,绑定不会激活。他们可能首先检索或不检索该值,但他们稍后会订阅PropertyChanged
。
如果您想确保所有绑定都已到位,请不要订阅OnNavigatedTo
,而是使用Loaded
。
public partial class VPage : Page
{
public ViewModel viewModel;
public VPage()
{
DataContext = viewModel = new ViewModel();
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
viewModel.onNavigatedTo();
}
private void onTap(object sender, TappedRoutedEventArgs eventArgs) { viewModel.onTap(); }
}