I need to refresh Image on View
This my ViewPage:
<Image Grid.Row="1"
Grid.Column="1"
x:Name="OriginalImg"
Source="{Binding Orig}"
DataContext="{StaticResource MainViewModel}"/>
I'm using MVVMLibs package. And This is my ViewModel:
public class MainViewModel: ViewModelBase
{
private WriteableBitmap original = new WriteableBitmap(1280,720);
private WriteableBitmap temp = new WriteableBitmap(1280,720);
public WriteableBitmap Orig
{
get { return original; }
set
{
this.original = value;
base.RaisePropertyChanged("Orig");
}
}
public async Task<bool> ApplyEffectAsync(StorageFile file)
{
fileStream = await file.OpenAsync(FileAccessMode.Read);
temp.SetSource(fileStream);
Orig = temp;
}
}
But Image on my Page not displayed. What's my problem?
Problem is you are not really instantiating a new WriteableBitmap, just changing its source. So while it might work the first time, it certainly won't work after because the Dependency Property Manager won't know that your image changed unless its instace changes.
Try creating your temp WriteableBitmap in the ApplyEffectAsync method.
Related
The following is part of my View in which I have bound an Image to a property in my ViewModel:
<Image Source="{Binding Image}" Grid.Column="2" Grid.ColumnSpan="2"/>
My ViewModel is this:
public class MainWindowViewModel : INotifyPropertyChanged
{
public BitmapImage Image
{
get { return _image; }
set
{
_image = value;
OnPropertyChanged();
}
}
Action _makeScannerAlwaysOnAction;
private BitmapImage _image;
public MainWindowViewModel()
{
AddNewPersonCommand = new RelayCommand(OpenFrmAddNewPerson);
FingerPrintScannerDevice.FingerPrintScanner.Init();
MakeScannerAlwaysOn(null);
}
private void MakeScannerAlwaysOn(object obj)
{
_makeScannerAlwaysOnAction = MakeScannerOn;
_makeScannerAlwaysOnAction.BeginInvoke(Callback, null);
}
private void Callback(IAsyncResult ar)
{
FingerPrintScannerDevice.FingerPrintScanner.UnInit();
var objFingerPrintVerifier = new FingerPrintVerifier();
objFingerPrintVerifier.StartVerifingProcess();
var ms = new MemoryStream();
ms.Position = 0;
objFingerPrintVerifier.MatchPerson.Picture.Save(ms, ImageFormat.Png);
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
Thread.Sleep(2000);
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
//Image = bi;
_makeScannerAlwaysOnAction.BeginInvoke(Callback, null);
}
private void MakeScannerOn()
{
while (true)
{
if (FingerPrintScannerDevice.FingerPrintScanner.ScannerManager.Scanners[0].IsFingerOn)
{
return;
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
My Problem:
The problem is when I want to bind the Image it gives me the error
Must create DependencySource on same Thread as the DependencyObject
I have googled a lot and I have seen the post in SO but neither of them worked for me.
any kind of help would be very appreciated.
BitmapImage is DependencyObject so it does matter on which thread it has been created because you cannot access DependencyProperty of an object created on another thread unless it's a Freezable object and you can Freeze it.
Makes the current object unmodifiable and sets its IsFrozen property to true.
What you need to do is call Freeze before you update Image:
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
as pointed out by #AwkwardCoder here is Freezable Objects Overview
While bi.Freeze(); worked for me in one case, I've seen no difference from adding/removing
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
The second time I used DataTemplate in xaml and all the same classes as in the first case, but I kept getting the same Error.
This was a thing that helped:
Application.Current.Dispatcher.Invoke(() => Image = bi);
Maybe accepted answer can be improved because Dispatcher.CurrentDispatcher don't actually give you UI thread.
After searching far and wide, and getting nowhere, I decided to ask.
I have a .NET 5.0 WPF project I am working on, and I have to bind an URL (of an online image) to the source of an image on my form.
I have tried the following:
CoverImage.Source = new BitmapImage("https://somesite..com/img.png");
as well as binding it via XAML:
///XAML:
<Image Name="CoverImage"
Source="{Binding PreviewSource}"/>
///C#
public string PreviewSource { get; set; } = "https://somesite..com/img.png";
I have tried other solutions such as getting the image from a HrrpRequest and then creating it through a MemoryStream.
Using local images (that are on the pc) works without issues.
EDIT: mm8's solution started working for seemingly no reason (I have not touched the code at all since first testing)
new BitmapImage(new Uri("https://www.google.se/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png"))`
and
<Image Name="CoverImage" Source="https://www.google.se/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png"/>
...works just as expected on .NET 5.
Make sure that your URL is valid and reachable from your client machine.
Are you sure the datacontext is correct? It works for me in the app below.
Xaml Code
<Grid>
<Image Name="CoverImage" Source="{Binding ImageSource}"/>
</Grid>
ViewModel
class MainWindowViewModel : ViewModelBase
{
private BitmapImage _imageSource;
public BitmapImage ImageSource
{
get => _imageSource;
set => SetProperty(ref _imageSource, value);
}
public MainWindowViewModel()
{
ImageSource = new BitmapImage(new Uri("https://www.google.se/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png"));
}
}
ViewModelBase
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual bool SetProperty<T>(ref T member, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(member, value))
{
return false;
}
member = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
MainWindow.xaml.cs
public MainWindow()
{
DataContext = new MainWindowViewModel();
InitializeComponent();
}
I am still kind of new to Xamarin forms and now I am using the Ffimagloading library to display a gif through my viewmodel's "DisplayImage" property. But after certain conditions are met, I want to hide/unload the image, so that it is no longer there.
This is the CachedImage in my View:
<ffimage:CachedImage Grid.Column="0"
Source="{Binding DisplayImage}" />
And this is the corresponding part in my ViewModel:
private ImageSource displayImage;
public void DownloadAndAssignImage() {
try
{
var response = await this.DownloadFile(new Uri("..."));
if (response != null)
{
this.DisplayImage = ImageSource.FromStream(() => new MemoryStream(response));
}
}
catch (Exception e)
{
Log.Error(e);
}
}
public void HideImage()
{
// does not work
this.DisplayImage = null;
// does not work too
this.DisplayImage = new byte[0];
}
public ImageSource DisplayImage
{
get => this.displayImage;
set
{
this.displayImage= value;
this.RaisePropertyChanged();
}
}
How can I make it, so that the CachedImage shows nothing again after having assigned an ImageSource to it through "DownloadAndAssignImage()"? Setting the ImageSource to null or to an empty byte[] array does not work. How exactly do I need to modify the "HideImage()" method?
Thanks for your help in advance!
use IsVisible
<ffimage:CachedImage Grid.Column="0" IsVisible="{Binding ImageVisible}"
Source="{Binding DisplayImage}" />
then in your VM (you'll need to implement INotifyPropertyChanged)
ImageVisible = false;
I'm creating a simple windows store app in c#. When i'm binding my image control to display an image from code- behind, my screen goes black. Anyone know how i can solve the problem?
ImageService Class
public class ImageService
{
public Image Image { get; set; }
public ImageService()
{
var uri = new System.Uri("ms-appx:///assets/Logo.scale-100.png");
var bmp = new BitmapImage(uri);
Image.Source = bmp;
}
}
XAML file
<Image x:Name="image" HorizontalAlignment="Left" Height="223" Margin="394,279,0,0" VerticalAlignment="Top" Width="305" Source="{Binding Image, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Stretch="UniformToFill"/>
Use this:
public class ImageService
{
public Uri Image { get; set; }
public ImageService()
{
Image = new Uri("ms-appx:///assets/Logo.scale-100.png");
}
}
The Source property of an Image is of type ImageSource which can be easily replaced by a Uri. (MSDN).
Images in XAML have a built in converter so you can just bind to a Uri, you don't have to create an Image in the service.
Your service isn't implementing INotifyPropertyChanged so if you set your image in your service outside the constructor your view won't update.
I don't see in your code where you are instantiating your Image. Image will be null so when your view loads, the Image will be null resulting in a blank image on your view.
You mean like this? Cause it still makes the sceen go black.
public class ImageService : INotifyPropertyChanged
{
private Uri _uri;
public Uri Uri
{
get { return _uri; }
set
{
_uri = value;
OnPropertyChanged();
}
}
public ImageService()
{
Uri = new Uri("ms-appx///assets/Logo.scale-100.png");
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
The following is part of my View in which I have bound an Image to a property in my ViewModel:
<Image Source="{Binding Image}" Grid.Column="2" Grid.ColumnSpan="2"/>
My ViewModel is this:
public class MainWindowViewModel : INotifyPropertyChanged
{
public BitmapImage Image
{
get { return _image; }
set
{
_image = value;
OnPropertyChanged();
}
}
Action _makeScannerAlwaysOnAction;
private BitmapImage _image;
public MainWindowViewModel()
{
AddNewPersonCommand = new RelayCommand(OpenFrmAddNewPerson);
FingerPrintScannerDevice.FingerPrintScanner.Init();
MakeScannerAlwaysOn(null);
}
private void MakeScannerAlwaysOn(object obj)
{
_makeScannerAlwaysOnAction = MakeScannerOn;
_makeScannerAlwaysOnAction.BeginInvoke(Callback, null);
}
private void Callback(IAsyncResult ar)
{
FingerPrintScannerDevice.FingerPrintScanner.UnInit();
var objFingerPrintVerifier = new FingerPrintVerifier();
objFingerPrintVerifier.StartVerifingProcess();
var ms = new MemoryStream();
ms.Position = 0;
objFingerPrintVerifier.MatchPerson.Picture.Save(ms, ImageFormat.Png);
var bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
Thread.Sleep(2000);
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
//Image = bi;
_makeScannerAlwaysOnAction.BeginInvoke(Callback, null);
}
private void MakeScannerOn()
{
while (true)
{
if (FingerPrintScannerDevice.FingerPrintScanner.ScannerManager.Scanners[0].IsFingerOn)
{
return;
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
My Problem:
The problem is when I want to bind the Image it gives me the error
Must create DependencySource on same Thread as the DependencyObject
I have googled a lot and I have seen the post in SO but neither of them worked for me.
any kind of help would be very appreciated.
BitmapImage is DependencyObject so it does matter on which thread it has been created because you cannot access DependencyProperty of an object created on another thread unless it's a Freezable object and you can Freeze it.
Makes the current object unmodifiable and sets its IsFrozen property to true.
What you need to do is call Freeze before you update Image:
bi.BeginInit();
bi.StreamSource = ms;
bi.EndInit();
bi.Freeze();
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
as pointed out by #AwkwardCoder here is Freezable Objects Overview
While bi.Freeze(); worked for me in one case, I've seen no difference from adding/removing
Dispatcher.CurrentDispatcher.Invoke(() => Image = bi);
The second time I used DataTemplate in xaml and all the same classes as in the first case, but I kept getting the same Error.
This was a thing that helped:
Application.Current.Dispatcher.Invoke(() => Image = bi);
Maybe accepted answer can be improved because Dispatcher.CurrentDispatcher don't actually give you UI thread.