【问题标题】:MVVM: OnBindingContextChange: PropertyChanged not firing in new view modelMVVM:OnBindingContextChange:PropertyChanged 未在新视图模型中触发
【发布时间】:2020-05-09 15:06:01
【问题描述】:

我正在编写 Xamarin 应用程序并尽我所能遵守 MVVM,我真的很喜欢

我的 ContentPages 通常包含对视图的引用。

我将绑定上下文设置为Page中的VM,然后在视图中使用OnBindingContextChanged

这允许我使用 PropertyChanged 方法来响应我的视图的显示逻辑条件

我已经成功使用了几次,但我很困惑为什么额外的实现不起作用

页面是这样的

public partial class BindingTextPage : ContentPage
{
    public BindingTextPage()
    {
        InitializeComponent();

        this.BindingContext = new ViewModels.LocationsViewModel();
    }
}

视图看起来像这样

private LocationsViewModel_vm;

public BindingTestView()
{
    InitializeComponent();

    System.Diagnostics.Debug.WriteLine("Debug: Initialised BindingTesView view");

}

protected override void OnBindingContextChanged()
{
    System.Diagnostics.Debug.WriteLine("Debug: BindingTest: OnBindingContextChanged: Context " + this.BindingContext.GetType());

    _vm = BindingContext as LocationsViewModel;

    _vm.PropertyChanged += _vm_PropertyChanged;
}

private void _vm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    try
    {
        System.Diagnostics.Debug.WriteLine("Debug: BindingTest: Method called");
        System.Diagnostics.Debug.WriteLine("Debug: BindingTest: Property " + e.PropertyName);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine("Debug: BindingTestView: Error changing context " + ex.Message);
    }
}

视图模型的提取,在这种情况下非常简单地设置一个字符串并因此更改一个属性,我预计这会导致 PropertyChange 触发?

public LocationsViewModel()
{
    tempMessage = "this is from the view model";
}

public string tempMessage
{
    get
    {
        return _tempMessage;
    }
    set
    {
        _tempMessage = value;
        OnPropertyChanged(nameof(tempMessage));
    }
}

我在启动时的调试语句显示 OnBindingContextChange 正在被调用,但在这个实例中 _vm_PropertyChanged 永远不会触发?我希望将 tempMessage 设置为这样做?

【问题讨论】:

    标签: mvvm xamarin.forms viewmodel


    【解决方案1】:

    您的代码中的事件顺序如下

    • LocationsViewModel 的构造函数被调用
    • 从您的构造函数中,您正在设置tempMessage
    • tempMessage 的 setter 调用了OnPropertyChanged,由于事件目前是null,所以没有触发
    • LocationsViewModel 的构造函数被留下
    • Page.BindingContext 已设置
    • OnBindingContextChanged 被调用
    • LocationsViewModel.PropertyChanged 已被您的页面订阅

    由于在您的页面订阅之前引发(或尝试)该事件,因此您的页面根本不会收到有关正在引发的事件的通知。如果您在订阅事件后设置值,则将按预期调用处理程序。

    例如

    protected override void OnBindingContextChanged()
    {
        _vm = BindingContext as LocationsViewModel;
    
        _vm.PropertyChanged += _vm_PropertyChanged;
    
        _vm.tempMessage = "Hello, world!"; // clichée , I know
    }
    

    【讨论】:

    • 我认为它必须与事件的顺序有关 - 在几乎所有其他使用它的情况下,都会调用 API 或响应按钮单击。我错误地认为在构造函数中设置 tempMessage 的值会异步发生,但我现在明白我的错误了。谢谢
    猜你喜欢
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多