PropertyChangedEventHandler准备工作

时间:2017-04-13 02:07:24

标签: c# wpf windows mvvm

我最初有一个异步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被触发。

当我有完整的异步模式时,我认为这是一个线程问题,但现在显而易见的是它更简单了。

1 个答案:

答案 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(); }
}