XAML x:在最初的null属性上绑定oneTime仍然有效。为什么?

时间:2017-07-25 02:18:25

标签: c# xaml uwp

x:绑定默认为OneTime,当Page的Loading事件触发生成的代码的Initialize函数时,它会使用数据更新目标UI。

我有一个带有ViewModel属性的页面。此ViewModel类为其属性实现INPC。只有在加载页面后,才会异步加载viewModel的数据。因此,在页面初始化和随后生成的代码初始化时,使用x:Bind的UI目标将具有空数据。

由于它是OneTime,除非我手动调用更新(我不会),否则它不应该改变。

那么为什么我的x:Bind UI工作?

以下是一些简化的代码片段。

<Page x:Name="MyPage" x:Class="MyProject.Pages.MyPage">
  <Button Command="{x:Bind ViewModel.GoToAnotherPageCommand}">


public sealed partial class MyPage : Page
{
    public MyPageViewModel ViewModel { get; set; }

    public MyPage()
    {
        this.InitializeComponent();
    }

    // called by an event bound to a Frame's Navigated, which all pages use
    public void OnNavigatedTo()
    {
        this.ViewModel = new MyPageViewModel();
    }
}

public class MyPageViewModel : INotifyPropertyChanged, INotifyPropertyChanging
{
    // GoToAnotherPageCommand is an INPC property and its set in the constructor

2 个答案:

答案 0 :(得分:2)

您的命令正常工作的原因是因为OnNavigatedTo在命令实例化之前将被称为。这意味着在代码尝试设置命令时,ViewModel已经实例化,不再是null

为证明我的观点,首先在以下路径下打开文件(可能是 ARM 或* x64,具体取决于您运行的是哪个平台) -

  

OBJ / 86 /调试/ MyPage.g.cs

这基本上是代码生成的文件,它连接了页面的所有x:Bind内容。

现在将断点放在命令设置的位置。就我而言,这是一个名为Set_Windows_UI_Xaml_Controls_Primitives_ButtonBase_Command的方法。然后将另一个断点放在OnNavigatedTo

现在运行应用程序,您将看到首先调用OnNavigatedTo方法。

如果您的网页NavigationCacheMode设置为Disabled,则此行为会使OnNavigatedTo成为实例化x:Bind绑定的理想位置,因此页面仅使用内存来创建这些新对象当用户实际导航到它时,而不是在页面构造函数中执行所有操作。

不要在Loaded的{​​{1}}事件中执行此操作。因为在命令实例化后会被称为。您可以尝试以下代码来实例化Page,结果非常不同(您的命令将无效)。

ViewModel

答案 1 :(得分:1)

编译的绑定系统(x:Bind)非常智能,可以检查初始空值,而不会将它们视为您希望绑定的实际值。它将等待第一个非null值并绑定该值。

这是设计原因,因为绑定到初始空值(几乎)绝不是绑定的意图。

我没有找到这些信息的来源,但我相信这是在2015年详细介绍x:Bind系统的Build talk中。

<强>更新

正如Justin在下面的评论和他自己的回答中提到的,如果在绑定操作发生后设置了视图模型,绑定将不起作用。

我相信这是因为绑定在属性链中遇到空引用时会终止,但我没有对此进行测试,所以我可能不正确。