WPF image source gif animation - c#

How do I get the GIF animated to work with the code below? The problem is the image will change accordinly to few different image.
WPF:
<Image Source="{Binding ElementName=L, Path=Image}" Height="400" Width="600" Stretch="None" />
Code behind:
public readonly DependencyProperty ImageProperty;
public ImageSource ImageStatus
{
get { return (ImageSource)GetValue(ImageProperty); }
set { SetValue(ImageProperty, value); }
}
Image = new BitmapImage(new Uri("/L;component/Images/test.gif", UriKind.Relative));
EDITED:
http://eladm.wordpress.com/2009/04/02/animated-gif-support-behavior/

I have used this to make my gifs work: http://www.vcskicks.com/csharp_animated_gif.php
[edit]
I have found something for WPF: http://wpfanimatedgif.codeplex.com/
But I didn't test it!

Related

Call GIF image source from the code behind in WPF c# for the tabcontrol's setter

i am using wpf tab control and setting the Icon and text in the tab header through style, i am able to set the text dynamically through getter and setter but can not able to set the image source. I tried to bind the image source through getter and setter but failed. Following is the style code in which i want to set the image source dynamically from the code behind.
-->
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<Image gif:ImageBehavior.AnimatedSource="{DynamicResource MyFillBrush}" Width="20" />-->
<Image gif:ImageBehavior.AnimatedSource="25.gif" Width="20" />
<Label Content="{Binding }"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
I know this is a bit old thread, but this is how you update the AnimatedSource from code:
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(value);
image.EndInit();
ImageBehavior.SetAnimatedSource(Imagereference, image);
The 'value' is the location of your gif file such as "25.gif".
The Imagereference is the Image control you want to update. Also ensure you have the namespace referenced: using WpfAnimatedGif;
Maybe you can use Binding, something like
private string _dynamicGif = "test.gif";
public string DynamicGif
{
get { return _dynamicGif; }
private set
{
_dynamicGif = value;
RaisePropertyChanged("DynamicGif");
}
}
and
<Image gif:ImageBehavior.AnimatedSource="{Binding DynamicGif, UpdateSourceTrigger=PropertyChanged}" Width="20" />
Or, if it doesn't work, you can use MediaElement instead of Image, it won't require WPF Animated GIF. It's also pretty simple to use:
private Uri _imgSource = new Uri("test.gif");
public Uri ImgSource
{
get { return _imgSource; }
private set
{
_imgSource = value;
RaisePropertyChanged("ImgSource");
}
}
and
<MediaElement x:Name="gifImg" LoadedBehavior="Play" Width="20" Source="{Binding ImgSource}"/>
Hope this helps.

ImageFailed with GridView

I have a problem with GridView and multiple items. Each of the item has image in it, source is online image, bound to property, like this:
<GridView x:Name="gridView" Width="710" ItemTemplate="{StaticResource FirstTemplate}" AllowDrop="True" CanDragItems="True" CanReorderItems="True">
<DataTemplate x:Key="FirstTemplate">
<Grid HorizontalAlignment="Left" Width="306" Height="210">
<Border Background="White" Opacity="0.1"/>
<Image Stretch="Uniform" Width="190" Height="100" Margin="0,50,0,0" ImageFailed="ImageFailed" Source="{Binding ImagePath}"/>
</Grid>
</DataTemplate>
Image paths are like this:
www.example.com/images/1.png
www.example.com/images/2.png
www.example.com/images/3.png
and so on...
If some image not exist, for example www.example.com/images/29.png, I use the event ImageFailed, which change the source of the image to image that is located in my project (default image). Code in this event:
private void ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
var image = sender as Image;
image.Source = new BitmapImage(new Uri("ms-appx:///Images/default.png"));
}
And this is working just fine, the default image is shown in the items that don't have images. But, when I scroll down the gridview, and then return to the beginning, images are messed up. Some items that had their images, now have the default image. Again when I scroll the gridview, and then return, again random changes with images.
Is this some cache problem? What could be the problem here? Or is there any better way of setting the default image source?
The source of your problem could be virtualization, i.e. reuse of item containers. When you replace a failed image by a fallback image in your ImageFailed handler, you are effectively replacing the Binding by a fixed value, so that the item container will later always show only the fallback image.
You may instead implement the ImageFailed handler in the view model, so that replacing the image with a fallback image won't break the Binding.
Add another property, e.g. Image to your item class
public class ImageItem
{
public string ImagePath { get; set; }
private BitmapImage image;
public BitmapImage Image
{
get
{
if (image == null)
{
image = new BitmapImage();
image.ImageFailed += (s, e) =>
image.UriSource = new Uri("ms-appx:///Images/default.png");
image.UriSource = new Uri(ImagePath);
}
return image;
}
}
}
and change the Binding to this:
<Image ... Source="{Binding Image}"/> // no ImageFailed handler here

Force an update to a control that's bound to the InkCanvas

I have the following XAML:
<Image Visibility="Visible"
Source="{Binding ElementName=inkCanvas,
Converter={StaticResource InkCanvasToImageSource},
UpdateSourceTrigger=PropertyChanged}">
</Image>
<InkCanvas x:Name="inkCanvas" />
What I'm trying to do is to convert the InkCanvas Stroke Collection into a BitmapImage. I'm using MVVM, and want to do this on a command. The problem that I have is that the above code will not trigger the converter to fire. I'm using UWP, so I can only pass one of the controls as a command parameter.
I need a method to convert from one to the other, but I'd like to do it inside the ViewModel.
An InkCanvas control is associated with an instance of an InkPresenter object (exposed through the InkPresenter property). The InkPresenter provides properties, methods, and events for managing the input, processing, and rendering of ink data for an InkCanvas control. So binding to InkCanvas won't trigger your converter to fire as the ink input is managed entirely by the InkPresenter. And InkCanvas.InkPresenter property is not a dependency property, we can't bind to this property. So we can't force the Image update with bingding to InkCanvas. We have to do it in code-behind and this may break the MVVM design.
To update the Image, we can use StrokesCollected and StrokesErased event to detect ink input and in these event save all InkStroke objects to a BitmapImage. For example:
In the XAML
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Image x:Name="MyImage" />
<Border Grid.Row="1" BorderBrush="Red" BorderThickness="2">
<InkCanvas x:Name="inkCanvas" />
</Border>
</Grid>
And in the code-behind:
public MainPage()
{
this.InitializeComponent();
...
inkCanvas.InkPresenter.StrokesCollected += InkPresenter_StrokesCollected;
inkCanvas.InkPresenter.StrokesErased += InkPresenter_StrokesErased;
}
private async void InkPresenter_StrokesErased(InkPresenter sender, InkStrokesErasedEventArgs args)
{
var image = await SaveAsync();
MyImage.Source = image;
}
private async void InkPresenter_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
{
var image = await SaveAsync();
MyImage.Source = image;
}
private async Task<BitmapImage> SaveAsync()
{
var bitmap = new BitmapImage();
if (inkCanvas.InkPresenter.StrokeContainer.GetStrokes().Count > 0)
{
try
{
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await inkCanvas.InkPresenter.StrokeContainer.SaveAsync(stream);
stream.Seek(0);
bitmap.SetSource(stream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
}
return bitmap;
}
Here I just set the image to MyImage, you can also set it to your ViewModel and use Binding in the Image.

Error Binding ContentControl to Image from Resource Dictionary

<Grid x:Name="ContentGrid">
<Grid.Resources>
<Image x:Key="art" Source="art.png" Stretch="None" />
</Grid.Resources>
<ContentControl Content="{Binding MyImg}" />
</Grid>
public Image MyImg
{
get { return (Image)GetValue(MyImgProperty); }
set { SetValue(MyImgProperty, value); }
}
public static readonly DependencyProperty MyImgProperty =
DependencyProperty.Register("MyImg", typeof(Image), typeof(MainPage), null);
public MainPage()
{
InitializeComponent();
ContentGrid.DataContext = this;
// Works.
MyImg = new Image() { Source = new BitmapImage(new Uri("art.png", UriKind.Relative)), Stretch = Stretch.None };
// Doesn't Work. Exception The parameter is incorrect. ???
MyImg = ContentGrid.Resources["art"] as Image;
}
ContentGrid.Resources["art"] as Image don't reuturn null but an image with the same source as art.png but assigning to the dependency property fails! why?
The second line isn't working because the image that you're referencing--the image in resources--doesn't have the source set up properly. In the first line, the one that works, you are properly setting up a BitmapImage and using a URI to reference the image. Your image in resources does not do that.
Therefore, try replacing your image in resources with this code:
<Image x:Key="art" Stretch="None">
<Image.Source>
<BitmapImage UriSource="art.png" />
</Image.Source>
</Image>

How do I bind an Image dynamically in XAML?

The following displays an image correctly in a silverlight usercontrol:
Image image = pagingManager.BaseApp.DatasourceManager.GetImage("helloWorld1");
ContentArea.Content = image;
...
<ContentControl x:Name="ContentArea"/>
However, I want to dynamically bind the image to XAML, e.g. like this:
#region ViewModelProperty: MainImage
private Image _mainImage;
public Image MainImage
{
get
{
return _mainImage;
}
set
{
_mainImage = value;
OnPropertyChanged("MainImage");
}
}
#endregion
...
MainImage = pagingManager.BaseApp.DatasourceManager.GetImage("helloWorld1");
And my XAML is this but the result is that it shows nothing:
<Image Source="{Binding MainImage}"/>
What do I need to put in my XAML to make it display the image object I have in my ViewModelProperty?
The Image.Source property is of type ImageSource, so your ViewModel should expose an ImageSource. Image is a control, it has nothing to do in the ViewModel.
If you do expose an Image control in your ViewModel (which is definitely a bad idea), then you should display it in a ContentControl, not an Image control :
<ContentControl Content="{Binding MainImage}" />

Categories