Reputation: 289
I am struggling to set the image source to the value I receive from the database. Here are relevant parts of my XAML, its code-behind and its view model.
XAML:
<Label Text="{Binding ViewModel_Fid}" />
<Image Source="{Binding ViewModel_ImageStream}" />
Code-behind:
protected override void OnAppearing() {
base.OnAppearing();
myViewModel = new myViewModel();
myViewModel.PopulateFid();
BindingContext = myViewModel;
}
View Model:
public event PropertyChangedEventHandler PropertyChanged;
private string _fid;
public async void PopulateFid() {
_fid = await getFid();
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ViewModel_Fid)));
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ViewModel_ImageStream)));
public MemoryStream ViewModel_ImageStream {
get {
byte[] buffer = myGetBytes(_fid);
return null == buffer ? null : new MemoryStream(buffer);
}
}
The problem is, ViewModel_ImageStream systematically executes BEFORE PopulateFid, which means that in ViewModel_ImageStream I always get _fid = null. I am pretty sure this is due to PopulateFid being async, but I need it to be this way, because getFid() is an external async function.
How can I enforce that PopulateFid executes before ViewModel_ImageStream is set?
Thanks!
PS. See my solution/answer below.
Upvotes: 1
Views: 242
Reputation: 289
What ultimately worked for me was adding the Image element at runtime (i.e., not specifying it in XAML). I add it once I've retrieved the necessary data in View Model.
So in Code-behind:
protected override void OnAppearing() {
base.OnAppearing();
myViewModel = new myViewModel();
myViewModel.PopulateFid();
BindingContext = myViewModel;
myViewModel.LoadImage = (obj) => {
var img = new Image();
img.Source = new StreamImageSource() {
Stream = (token) => getstream(token)
};
mainstack.Children.Add(img);
};
}
private async Task<Stream> getstream(object token) {
return new MemoryStream(myViewModel.myGetBytes);
}
in View Model:
private string _fid;
public async void PopulateFid() {
_fid = await getFid();
LoadImg?.Invoke(true);
}
Upvotes: 1