当我绑定到单个对象时,Xamarin Forms MVVM数据绑定失败

时间:2018-10-16 11:24:11

标签: mvvm data-binding xamarin.forms

当我通过按钮从ListView中单击时,在细节页面上的数据无法正确绑定时出现问题。 ListView完美地绑定,并且该对象被传递到详细信息页面。读取对象的ID,并从API调用对象的完整版本,并将其设置为对象的新实例。当我添加一个断点时,完整的对象可用,但是视图中的Labels没有被填充。这是ViewModel:

DetailsViewModel.cs

public class DetailsViewModel
{
    public Deal Deal { get; set; }
    public int DealId { get; set; }

    public DetailsViewModel(int id)
    {
        Deal = new Deal();
        DealId = id;
    }

    public async void GetDeal()
    {
        var deal = await Deal.GetDeal(DealId);
        if(deal != null)
        {
            Deal = deal;
        }
    }
}

后面的代码如下:

DetailPage.Xaml.cs

DetailsViewModel viewModel;
    int dealId;

    public DetailPage(int id)
    {
        InitializeComponent();

        dealId = id;
        viewModel = new DetailsViewModel(dealId);
        BindingContext = viewModel;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();
        viewModel.GetDeal();
    }

Xaml文件是

DetailPage.Xaml

 <ContentPage.Content>
    <ScrollView>
        <StackLayout x:Name="detailsLayout">

            <Label Text="{Binding Deal.Name}" />

        </StackLayout>
    </ScrollView>

</ContentPage.Content>

当我在DetailsViewModel上的Deal = deal中设置断点时,Deal对象存在并且具有正确的数据,但是我只是得到了一个空白屏幕。我已经尝试使用Text =“ {Binding Name}”和Text =“ {Binding Deal.Name}”的标签。

我还尝试过在ViewModel的GetDeal函数中手动创建交易,但仍然没有任何约束。

1 个答案:

答案 0 :(得分:0)

1)确保您的属性将实现INotifyPropertyChanged接口的更改通知UI。参见https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm

2)确保使用Device.BeginInvokeOnMainThread在UI线程上完成设置。 https://docs.microsoft.com/fr-fr/dotnet/api/xamarin.forms.device.begininvokeonmainthread?view=xamarin-forms

using System.ComponentModel;
using System.Runtime.CompilerServices;
using Xamarin.Forms;

namespace YourNamespace
{
    public class DetailsViewModel : INotifyPropertyChanged
    {
        private Deal _deal;

        public Deal Deal
        {
            get => _deal;
            set
            {
                if (_deal != value)
                {
                    _deal = value;
                    OnPropertyChanged();
                }
            }
        }
        public int DealId { get; set; }

        public DetailsViewModel(int id)
        {
            //!! useless assignation
            //Deal = new Deal();
            DealId = id;
        }



        public async void GetDeal()
        {
            var deal = await Deal.GetDeal(DealId);

            if (deal != null)
            {
                //Ensure we are on UI thread
                Device.BeginInvokeOnMainThread(() => Deal = deal);
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }
}