In c# I am making an application using the xaml designer.
PROBLEM: IF I CHANGE THE IMAGE SOURCE INTO ANOTHER IMAGE SOURCE, NOTHING APPEARS: THOUGH, IF THE IMAGE WAS ALREADY DEFINED, IT CHANGED INTO "NULL" (NO IMAGE)
I have used a method (which I found on the web) to change an imagesource (string) into an image(object).
I've tried multiple times to change the image source of some xaml pictures by just changes the imagesource in xaml into another image (that I put in the project) but unfortunately the image is not visible when I do it this way.
The image and method I used are the following ones:
ms-appx:///Assets/bank_employee.jpg"
imageFromXaml.Source = imgCreatedFromMethod.Source;
private static Image srcToImage(string source)
{
Uri imageUri = new Uri(source);
BitmapImage imageBitmap = new BitmapImage(imageUri);
Image img = new Image();
img.Source = imageBitmap;
return img;
}
Does anyone of you know what the problem could be?
I had a similar problem, and this worked for me:
var imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.StreamSource = memoryStream;
imageSource.CacheOption = BitmapCacheOption.OnLoad;
imageSource.EndInit();
Have you tried binding the source in XAML to a URI and then updating that?
Like this:
<Image Source="{Binding ImageUri}" />
Then having a property somewhere in your datacontext which would be like:
public class myClass: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private Uri imageUri;
public Uri ImageUri
{
get
{
return imageUri;
}
set
{
imageUri = value;
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ImageUri"));
}
}
}
}
Have you verified that your method actually succeeds and returns the correct image source? If it does there should be no problem reassigning Source. If you load the newly created image itself into the UI, does it retain its source?
this.Content = imgCreatedFromMethod; // where "this" is the window
By the way, it would not be necessary to implement your own conversion function. If you have a string that would be valid as XAML, you can directly call the converter that the XAML parser uses to build an image source:
using System.Globalization;
using System.Windows.Media;
string stringValue = ...
ImageSourceConverter converter = new ImageSourceConverter();
ImageSource imageSource = converter.ConvertFrom(
null, CultureInfo.CurrentUICulture, stringValue);
The converter instance (an ImageSourceConverter in this case) can also be retrieved dynamically by System.ComponentModel.TypeDescriptor.GetConverter(typeof(TypeToConvertTo)).
This conversion will also be done automatically if you use data-binding as in TylerD87's answer. You can also look into triggers and define both images in the style like this:
<Image>
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="original path" />
<Style.Triggers>
<Trigger ...>
<Setter Property="Source" Value="new path" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Related
I am working on a UWP project with xaml and c#. I have a stackpanel of images on the right where you can click on the image and it will display a related larger image to the left of the stackpanel.
The large image is set initially to the "large" image that relates to the first "small" image in the stackpanel when you load the page but when you click any of the other small images in the stackpanel, the large image does not update.
The whole thing is a datatemplate that is placed inside a flyout. The relevant xaml for the "large" image is here:
<Border Background="White" Grid.Row="2">
<Image Stretch="Uniform">
<Image.Source>
<BitmapImage UriSource="{Binding SelectedImage}" />
</Image.Source>
</Image>
</Border>
When the small image is clicked, it triggers the "tapped" method for that image and that method is:
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
var img = ((Windows.UI.Xaml.Controls.Image)sender).DataContext as obj
img.FlyoutContent.SelectedImage = new Uri(img.relatedPath);
}
I am using the above code to set the image initially and it works. It just does not change the large image when the small one is clicked.
In debugging, when I click on the small image in the stackpanel, I break at the "image tapped" method and I can see that the uri is getting updated properly and there are no binding errors. The UI never changes.
What am I missing?
Thank you,
Zach
*Side note: the "obj" is just a made up name of a custom class.
For Binding properties you need to implement INotifyPropertyChangedclass so that the UI gets updated automatically.
class CustomClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _imageLink;
public string ImageLink
{
get
{
return _imageLink;
}
set
{
_imageLink = value;
RaisePropertyChanged();
}
}
private void RaisePropertyChanged([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Or as you are using a Tapped event, why not give your XAML element a x:name and set the source of the image of that name to your URi.
To update the ImageLink property, you need to create an instance of the CustomClass in the page you are changing the property.
CustomClass ab = new CustomClass();
ab.ImageLink = "code here";
I have this ResourceDictionary in Main.xaml:
<Window.Resources>
<ResourceDictionary>
<BitmapImage x:Key="Customer" UriSource="Icons/customer.png"/>
<BitmapImage x:Key="Project" UriSource="Icons/project.png"/>
<BitmapImage x:Key="Task" UriSource="Icons/task.png"/>
</ResourceDictionary>
</Window.Resources>
I initially set the image using:
<Image Name="TypeIcon" HorizontalAlignment="Left" VerticalAlignment="Center"
Source="{StaticResource Customer}" Height="16" Width="16"/>
I'm trying to change TypeIcon's Source from Customer to Project in a C# method.
I've tried using:
TypeIcon.Source = "{StaticResource Project}";
But I get this error:
Cannot implicitly convert type string to System.Windows.Media.ImageSource
I've tried defining the image using new ImageSource(), but this doesn't work either.
How can I change the image's Source programmatically in C#?
After much Googling, whilst writing this question, I figured out how to do it:
TypeIcon.Source = (ImageSource) Resources["Project"];
It is not for static resources but perhaps will be useful anyway... :)
i.e. how to set background for Grid dynamically
var myBrush = new ImageBrush();
var image = new Image
{
Source = new BitmapImage(
new Uri(
"pack://application:,,,/YourAppName;component/Images/Boo.png"))
};
myBrush.ImageSource = image.Source;
MainGrid.Background = myBrush;
i.e. how to set icon of the app dynamically
var idleIco = new Image
{
Source = new BitmapImage(
new Uri(
"pack://application:,,,/YourAppName;component/Images/idle.ico"))
};
SomeObjectYouAreUsingToSet.IconSource =idleIco.Source;
You can use the ImageSourceConverter class to get what you want, for example:
img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");
I have an image file selected by user whose name is 'img'. How can I bind my Image control (given below) to this file?
<Image Source = "{Binding ImagePath}" />
I wrote:
ImagePath = new Uri(img.Path);
But it does not work. Can anyone help me?
After your image is loaded, create a BitmapImage.
var bi = new BitmapImage();
var fstream = await selectedFile.OpenAsync(FileAccessMode.Read);
bi.SetSource(fstream);
BImage = bi;
Then make sure your BImage property notifies the UI. I renamed ImagePath to BImage to clarify that it's not using the Path directly, but you can call it whatever you like.
private BitmapImage _bImage;
public BitmapImage BImage
{
get { return _bImage; }
set
{
_bImage= value;
NotifyPropertyChanged("BImage");
}
}
(Your XAML)
<Image Source = "{Binding BImage}" />
I am trying to retrieve the image from resource file and tryin to bind it to the datagrid of my WPF application.
The datagrid is somewhat like this:
<DataGridTemplateColumn Header="Image" Width="45">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Path=Icon}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
And Image is a property of type image of my MVVm class like this:
public Image Icon
{
get { return _licenseImage; }
set { _licenseImage = value;
PropertChanged("Icon");}
}
And in the code behind Im tryin to do something like this to get image from resource file and tryin to bind it to datagrid column.
ResourceManager resourceManager =
new ResourceManager("Resources.Images", Assembly.GetExecutingAssembly());
BitMap bitmap = resourceManager.GetObject("okimage") as BitMap;
Image image = bitmap;
return image;
I can see that image is populated but it is not displaying in the grid.
You should bind to an ImageSource instead of Image.
we use this helper class:
public static class ImageSourceHelper
{
public static ImageSource GetResourceImage(string resourcePath)
{
return GetResourceImage(Assembly.GetCallingAssembly(), resourcePath);
}
public static ImageSource GetResourceImage(Assembly resourceAssembly, string resourcePath)
{
if (string.IsNullOrEmpty(resourcePath)) return null;
var assembly = resourceAssembly.GetName().Name;
const string uriFormat = "pack://application:,,,/{0};component/{1}";
if (!UriParser.IsKnownScheme("pack")) new System.Windows.Application();
var uri = new Uri(string.Format(uriFormat, assembly, resourcePath), UriKind.RelativeOrAbsolute);
return BitmapFrame.Create(uri);
}
public static ImageSource ConvertFromGdiBitmap(Bitmap bitmap)
{
return Common.SystemAbstraction.Media.ImageConverter.ConvertToBitmapSource(bitmap);
}
public static Bitmap ConvertToGdiBitmap(ImageSource imageSource)
{
return Common.SystemAbstraction.Media.ImageConverter.ConvertToBitmap(imageSource as BitmapSource);
}
}
It creates an ImageSource from Bitmap or resource images.
Usage is
img.Source = ImageSourceHelper("Path/To/Your/Image.png");
or
var resourceAssembly = // get resource assembly...
img.Source = ImageSourceHelper(resourceAssembly, "Path/To/Your/Image.png");
if the image is contained in an other assembly than the currently calling assembly.
The path of your image is the path starting at the project file root of your assembly.
Say you have an folder images your path will be "images/somepicture.png".
I think the problem is that you are binding to the wrong property. Try this:
<Image Source="{Binding Path=Icon}" />
I have an image control on a Window in my WPF project
XAML:
<Image
Source="{Binding NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"
Binding.SourceUpdated="bgMovie_SourceUpdated"
Binding.TargetUpdated="bgMovie_TargetUpdated" />
In code I am changing the source of the image
C#:
myImage = new BitmapImage();
myImage.BeginInit();
myImage.UriSource = new Uri(path);
myImage.EndInit();
this.bgMovie.Source = myImage;
But the bgMovie_SourceUpdated event is never triggered.
Can anyone shed some light on what I'm doing wrong?
By assiging a value directly to the Source property, you're "unbinding" it... Your Image control is not databound anymore, it just has a local value.
In 4.0 you could use the SetCurrentValue method:
this.bgMovie.SetCurrentValue(Image.SourceProperty, myImage);
Unfortunately this method isn't available in 3.5, and there is no easy alternative...
Anyway, what are you trying to do exactly ? What is the point of binding the Source property if you're setting it manually anyway ? If you want to detect when the Source property changes, you can use the DependencyPropertyDescriptor.AddValueChanged method:
var prop = DependencyPropertyDescriptor.FromProperty(Image.SourceProperty, typeof(Image));
prop.AddValueChanged(this.bgMovie, SourceChangedHandler);
...
void SourceChangedHandler(object sender, EventArgs e)
{
}
By hard-coding the Source in the code, you are breaking the Binding in your XAML.
Instead of doing that, bind to a property that you set using (most of) the same code above. Here's one way to do that.
XAML:
<Image Name="bgMovie"
Source="{Binding MovieImageSource,
NotifyOnSourceUpdated=True,
NotifyOnTargetUpdated=True}"
Binding.SourceUpdated="bgMovie_SourceUpdated"
Binding.TargetUpdated="bgMovie_TargetUpdated" />
C#:
public ImageSource MovieImageSource
{
get { return mMovieImageSource; }
// Set property sets the property and implements INotifyPropertyChanged
set { SetProperty("MovieImageSource", ref mMovieImageSource, value); }
}
void SetMovieSource(string path)
{
myImage = new BitmapImage();
myImage.BeginInit();
myImage.UriSource = new Uri(path);
myImage.EndInit();
this.MovieImageSource = myImage;
}