【问题标题】:Async method populating XAML binded fields inconsistently异步方法不一致地填充 XAML 绑定字段
【发布时间】:2020-01-26 04:22:51
【问题描述】:

我有一个由两个不同的模型填充的视图。对于我的应用,这意味着两个不同的 Services 用于获取这些各自模型的数据。

现在数据根本不会填充。我是什么意思?目前,页面加载时仅显示Group.Name。其余的 User 标签不显示。在三个标签显示之前,我必须创建一个按钮来更改 User 绑定对象中的一个字段。

注意: BaseViewModel 继承 INotifyPropertyChangedIPageLifecycleAwareSetProperty() 在属性更改时引发事件。

查看

<StackLayout Margin="10" VerticalOptions="StartAndExpand">
    <Grid>
        <Label Grid.Row="0" Text="{Binding User.Name}"/>
        <Label Grid.Row="1" Text="{Binding User.Age}"/>
        <Label Grid.Row="2" Text="{Binding User.Occupation}"/>
        <Label Grid.Row="3" Text="{Binding Group.Name}"/>
    </Grid>
</StackLayout>

视图模型

public class ProfileViewModel : BaseViewModel
{
    private IGroupService _groupService;
    private IUserService _userService;
    public ProfileViewModel(IGroupService groupService, IUserService userService)
    {
        _groupService = groupService;
        _userService = userService;
        GetUser();
        GetGroup();
    }

    private async void GetUser()
    {
        var user = await _userService.GetUserAsync();
        User = user;
        SetProfilePhoto();
    }

    private async void GetGroup()
    {
        var group = await _groupService.GetGroupAsync();
        Group = group;
    }

    private void SetProfilePhoto()
    {
        var profilePhotoBytes = User.ProfilePhotoBytes;
        if (profilePhotoBytes == null || profilePhotoBytes.Length == 0)
            ProfilePhoto = ImageSource.FromResource("MyApp.Images.default_profile_picture.png");
        else
            ProfilePhoto = ImageSource.FromStream(() => new MemoryStream(profilePhotoBytes));
    }

    private ImageSource _profilePhoto;
    public ImageSource ProfilePhoto { get => _profilePhoto; set => SetProperty(ref _profilePhoto, value); }

    private User _user;
    public User User { get => _user; set => SetProperty(ref _user, value); 
    }
    private Group _group;
    public Group Group{ get => _group; set => SetProperty(ref _group, value); }
}

型号

public class User: BindableBase
{
    private string _id;
    public string Id { get => _id; set => SetProperty(ref _id, value); }

    private string _name;
    public string Name { get => _name; set => SetProperty(ref _name, value); }

    private string _age;
    public string Age { get => _age; set => SetProperty(ref _age, value); }

    private string _occupation;
    public string Occupation { get => _occupation; set => SetProperty(ref _occupation, value); }

    private byte[] _profilePhotoBytes;
    public byte[] ProfilePhotoBytes { get => _profilePhotoBytes; set => SetProperty(ref _profilePhotoBytes, value); }

    private ImageSource _profilePhoto;
    public ImageSource ProfilePhoto { get => _profilePhoto; set => SetProperty(ref _profilePhoto, value); }
}

public class Group: BindableBase
{
    private string _id;
    public string Id { get => _id; set => SetProperty(ref _id, value); }

    private string _name;
    public string Name { get => _name; set => SetProperty(ref _name, value); }

    private byte[] _groupPhotoBytes;
    public byte[] GroupPhotoBytes { get => _groupPhotoBytes; set => SetProperty(ref _groupPhotoBytes, value); }

    private string _createdUserId;
    public string CreatedUserId { get => _createdUserId; set => SetProperty(ref _createdUserId, value); }

    private DateTime _createdDate;
    public DateTime CreatedDate { get => _createdDate; set => SetProperty(ref _createdDate, value); }
}

【问题讨论】:

  • 更新: 我刚刚意识到,当我在 else 语句中通过 bytes 设置注释掉 ProfilePhotoBytes 时,这解决了问题。我已经测试了 15 次以确保它是一致的。这意味着该操作会以某种方式干扰被通知给前端的 User 对象的其余部分。请问有什么帮助吗?
  • 请下断点调试profilePhotoBytes是否获取到值。
  • 它肯定会得到一个值,因为照片被设置,然后文本没有;'t。但是,如果它转到默认照片,那么照片和文字都会显示。我注意到较低分辨率的照片没有这个问题。它很有趣。

标签: c# xaml xamarin xamarin.forms


【解决方案1】:

问题似乎很简单……

当您将类属性绑定到未实现 INotifyPropertyChanged 接口的 UI 元素时...对那些不反映您的 UI 元素后 UI 元素的属性所做的任何更改都已呈现...

最简单的解决方法是使用

实现您的模型类

INotifyPropertyChanged

界面...

当您使用 Prism 时,这可以通过继承来实现

可绑定基础

类...例如

public class Group : BindableBase
{
    string _id;
    public string Id { get => _id; set => SetProperty(ref _id, value); }
    string _name;
    public string Name { get => _name; set => SetProperty(ref _name, value); }

    public byte[] GroupPhotoBytes { get; set; } //change similarly like above
    public string CreatedUserId { get; set; } // to do 
    public DateTime CreatedDate { get; set; } // to do
}

完成上述更改后...现在您的 UI 将在您的属性更新时更新...

希望对你有帮助

【讨论】:

  • 谢谢,我同意应该在那里。无论如何,它仍然没有填充我的视图。实际上,我必须创建一个按钮并更改 User 的属性,因为其余的数据会加载。我已经更新了模型,所以你可以准确地看到我正在使用什么。我已更新问题以反映该问题。谢谢。
猜你喜欢
  • 2018-03-01
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-03
  • 2020-08-04
  • 2015-05-13
相关资源
最近更新 更多