Windows Template Studio UWP应用首次导航页面加载不全问题排查
页面首次导航内容显示不全?来排查WTS迁移的绑定时序问题
嘿,从Template10迁到Windows Template Studio时遇到这种首次加载缺内容、二次加载正常的情况,大概率是绑定时序或者ViewModel属性通知的问题,咱们结合你给的代码一步步捋:
先看你的代码细节
XAML部分
你用x:Bind绑定ViewModel.ItemFinalized控制整个StackPanel的可见性,里面的ToggleSwitch还绑定了HasLineItems这类属性:
<StackPanel Visibility="{x:Bind ViewModel.ItemFinalized, Mode=OneWay}"> <TextBlock TextWrapping="WrapWholeWords">This text</TextBlock> <ToggleSwitch x:Name="toggleSwitchSaveCopies2" Margin="0,0,0,0" IsOn="{x:Bind ViewModel.SavePdfCopies, Mode=TwoWay}" Visibility="{x:Bind ViewModel.HasLineItems, Mode=OneWay}" OffContent="Don't save PDF copies." OnContent="Save and show me the PDFs."></ToggleSwitch> <ToggleSwitch x:Name="toggleSwitchComposeEmail2" Margin="0,0,0,0" IsOn="{x:Bind ViewModel.ComposeEmail, Mode=TwoWay}" OffContent="Don't compose an email." OnContent="Compose an email."></ToggleSwitch> <Button x:Name="buttonSaveFinalized" IsEnabled="{x:Bind ViewModel.CanSave, Mode=OneWay}" Content="Save" Margin="0,12,0,20" Click="ButtonSaveFinalized_Click" /> <Button x:Name="buttonViewScanSheetPDF" Content="Test" Margin="0,25,0,20" Click="ButtonViewScanSheetPDF_Click" /> </StackPanel>
ViewModel部分
你的ItemFinalized属性用了基类的Set方法触发通知,还额外触发了IsDraft的通知:
public bool ItemFinalized { get => itemFinalized; set { Set(ref itemFinalized, value); RaisePropertyChanged("IsDraft"); } }
可能的原因&排查步骤
1. ViewModel初始化与属性赋值的时机不匹配
WTS和Template10在页面导航的ViewModel初始化逻辑上有差异:
- 如果你是在
OnNavigatedTo里初始化ViewModel或者加载数据,而且加载是异步的,那x:Bind完成初始绑定时,属性可能还没被赋值。比如:protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); // 异步加载数据,此时页面已经完成初始绑定 await ViewModel.LoadDataAsync(); } - 二次加载正常是因为WTS默认可能开启了页面导航缓存(
NavigationCacheMode.Enabled),缓存的ViewModel里属性已经是正确的值了。
解决:在异步加载完成后手动刷新绑定,或者确保属性赋值在绑定初始化前完成:
protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); await ViewModel.LoadDataAsync(); Bindings.Update(); // 强制刷新所有x:Bind绑定 }
2. 相关属性的PropertyChanged通知不完整
你给的ItemFinalized通知没问题,但要检查HasLineItems、CanSave这些绑定的属性是否也正确触发了通知:
- 比如
HasLineItems应该这样实现:private bool hasLineItems; public bool HasLineItems { get => hasLineItems; set => Set(ref hasLineItems, value); // 用基类Set方法自动触发通知 } - 如果这些属性值变化时没触发通知,x:Bind就不会更新UI,导致首次加载时内容不显示。
3. 检查ItemFinalized的初始值与赋值时机
- 看看
itemFinalized字段的初始值是不是false,如果首次加载时ViewModel初始化后没有把它设为true,那整个StackPanel会默认不可见。 - 确认在ViewModel的构造函数或者加载数据的方法里,是否正确设置了
ItemFinalized = true,而且这个赋值是在数据准备完成后执行的。
4. 临时关闭导航缓存验证
在页面构造函数里关闭缓存,看看二次加载是否也出现问题:
public YourPage() { this.InitializeComponent(); NavigationCacheMode = NavigationCacheMode.Disabled; }
如果二次加载也显示不全,那基本可以确定是首次加载时ViewModel的属性没有及时赋值并触发通知。
总结
最核心的问题就是首次导航时,UI绑定完成后ViewModel的属性才更新,或者属性更新时没有正确通知UI,而二次加载依赖缓存规避了这个问题。按照上面的步骤排查,应该能快速定位到问题~
内容的提问来源于stack exchange,提问作者Carlo Mendoza
相关产品推荐
相关产品推荐

