binding an image source in XAML - silverlight

I am trying to bind an image source to my XAML through c#
this works
<Image Source="images/man.jpg"></Image>
this does not work
<Image Source="images/{Binding imagesource}"></Image>
where imagesource is a string variable in the c# file of this xaml and is being set equal to "man.jpg"

here is a way how to do it in XAML:
add this to the namespace:
xmlns:System="clr-namespace:System;assembly=mscorlib"
then add your images paths
<System:String x:Key="ImageRefresh">/Theme;component/Images/icon_refresh.png</System:String>
<System:String x:Key="ImageSearch">/Theme;component/Images/icon_search.png</System:String>
This is how you use it
<Image Height="16" Source="{StaticResource ImageSearch}" Stretch="Uniform" Width="16"/>
This works ok, but if you load your xaml style in Blend it will go bogus..
An object of type "System.String" cannot be applied to a property that expects the type "System.Windows.Media.ImageSource".
I haven't figured out yet, how to replace System:String with that Media.ImageSource... but hey.. it works for me in Visual Studio.

You can't stick a binding mid-way through the value like that. It's either a binding, or it's not. Assuming imagesource is publicly accessible via your DataContext, you could do this:
<Image Source="{Binding imagesource}"/>
However, if it's been set to "man.jpg" then it won't find the image. Either set imagesource to the full path ("images/man.jpg") or use a converter:
<Image Source="{Binding imagesource, Converter={StaticResource RelativePathConverter}}"/>
The converter would prepend "images/" onto its value. However, it may be necessary for the converter to return an ImageSource rather than a string.

Images have bitten me in the past. There is a certain lookup order involved.
When you use "image/man.jpg" it could refer to a file inside your silverlight xap, or relative to the location of XAP file. For example, it could be in YourProject.Web/ClientBin/image/man.jpg.
You should troubleshoot by using full URLs first and find out if this works.

imagesource needs to be an actual Image object, not a string.
Here is a method that will create a new Image object given a path:
public BitmapImage Load(string path)
{
var uri = new Uri(path);
return new BitmapImage(uri);
}

Related

Using Bitmap Class in XAML [duplicate]

I have two .png files added to my resources which I need to access their Uri when doing binding.
My xaml code is as followed:
<Grid>
<Image>
<Image.Source>
<BitmapImage DecodePixelWidth="10" UriSource="{Binding Path=ImagePath}"/>
</Image.Source>
</Image>
</Grid>
and the binding code using ImagePath is:
ImagePath = resultInBinary.StartsWith("1") ? Properties.Resources.LedGreen : Properties.Resources.ledRed;
However
Properties.Resources.LedGreen
returns a Bitmap instead of String containing the Uri of that particular image.
I just want to know how to extract that value without a need to address a path of the image in the directory that it's stored. (Which honestly I am not sure is a right thing to do as I couldn't find any similar situation on the net).
Please let me know if there is even a preferred method to the one I am trying to use if available.
In a WPF application you would usually not store images in Properties/Resources.resx and access them by means of the Properties.Resources class.
Instead you just add the image files to your Visual Studio project as regular files, perhaps in a folder named "Images" or the like. Then you would set their Build Action to Resource, which is done in the Properties window. You get there e.g. by right-clicking the image file and select the Properties menu item. Note that the default value of the Build Action should be Resource for image files anyways.
In order to access these image resources from code you would then use a Pack URI. With the above folder name "Images" and an image file named "LedGreen.png", creating such an URI would look like this:
var uri = new Uri("pack://application:,,,/Images/LedGreen.png");
So you could perhaps declare your property to be of type Uri:
public Uri ImageUri { get; set; } // omitted INotifyPropertyChanged implementation
and set it like this:
ImageUri = resultInBinary.StartsWith("1")
? new Uri("pack://application:,,,/Images/LedGreen.png")
: new Uri("pack://application:,,,/Images/LedRed.png");
Finally your XAML should look like shown below, which relies on built-in type conversion from Uri to ImageSource:
<Grid>
<Image Width="10" Source="{Binding Path=ImageUri}" />
</Grid>
Declare the Properties.Resources.LedGreen property as ImageSource and set it to Uri location rather than the Bitmap object.
Or if you insist of storing it as a bitmap you can get the source by returning Properties.Resources.LedGreen.ImageSource which will be of type ImageSource.
I would prefer the first approach.

Binding against Image source property

I need to binding to image.source property.
this works obviusly:
<Image Source="/Intecsal.Generico.Recursos;component/Images/Flags/ES.png"/>
but, I have a var with the string "ES" and I want to do something like this:
<Image Source="{Binding var, StringFormat=/Intecsal.Generico.Recursos;component/Images/Flags/{0}.png}"/>
But this doesn't work.. the image is not shown.
Can someone help me? thanks!
It doesnt work that way. Source property has the type ImageSource and every string being passed through Binding will be converter to new ImageSource instance. Binding has internally many converters.
That is the reason why your StringFormat has no effect at all and it never will :)
However, you still have the option to use Converter in Binding that will convert your properties value into whatever you wish :)
Take a look at this code line:
<Image Source="{Binding Path=Whatever,
Converter={StaticResource WhateverToSourceConverter}"/>

How to set ImageSource in a codebehindfile

I have in a UserControl the Property ImageSource. How can I set the ImageSource in my code behind to a Image in my Resources directory?
I want to bind the Image Source to the property ImageSource.
<Image Source="{Binding Path=ImageSource}" />
In order to create a BitmapImage (which is derived from ImageSource) from a resource file in code, you would do the following, provided that the file MyImage.jpg is in a folder named Images of your Visual Studio project, and that its Build Action is set to Resource:
var uri = new Uri("pack://application:,,,/Images/MyImage.jpg");
ImageSource = new BitmapImage(uri); // set the ImageSource property
See also this answer.
You could also directly use the image resource without binding:
<Image Source="/Images/MyImage.jpg" />

Images bound to images added to resx files using XAML

My WPF application includes a resource file MyResources.resx, containing several strings and images. Because the application will need to be localized, all my references to globalized resources must be made via named properties of the auto-generated MyResources class. The following code works well for string resources:
<Button Content="{x:Static local:Properties.MyResources.ButtonText}" />
However the same does not work for images. Assuming I have an image eflag.bmp added to the resources as a resource named Flag, I would like to be able to do something like this:
<Image Source="{x:Static local:Properties.MyResources.Flag}" />
Please note that the following alternative approach:
<Image Source="/MyNamespace;component/Resources/eflag.bmp" />
cannot be used in this case because it will not be able to handle localization. The problem can be solved using code behind but I am looking for a XAML based solution.
Turn your x:Static into a Binding.Source and add a Converter which does Bitmap to ImageSource.
Source="{Binding Source={x:Static local:Properties.MyResources.Flag},
Converter={StaticResource BitmapToImageSourceConverter}}"
Alternatively you can make the converter a custom markup extension which takes a Bitmap and returns the ImageSource in ProvideValue.
Source="{me:BitmapToImageSource {x:Static local:Properties.MyResources.Flag}}"

WPF relative path problem

I have created a custom TaskButton control that takes an image and text. The properties are set like this:
<custom:TaskButton Text="Calendar" ImagePath="Images/calendar.png" ... />
My custom control class implements Text and ImagePath properties, and the control template for the custom control (in Themes\Generic.xaml) sets its content like this, using a RelativeSource object to get the image path:
<!-- Button Content -->
<StackPanel>
<Image Source="{Binding Path=ImagePath, RelativeSource={RelativeSource TemplatedParent}}" Width="24" Height="24" Stretch="Fill" Margin="10,0,0,0" />
<TextBlock Text="{TemplateBinding Text}" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Segoe UI" FontWeight="Bold" Margin="6,0,10,0" Foreground="Black" />
</StackPanel>
The control works fine in most cases, but in a particular project, the relative path to the button's image does not get resolved correctly, and the button image is not displayed. Here is what I have figured out so far:
I am entering the path correctly when I use the custom control. If I place an image control on the same design surface with the same relative path, it is resolved correctly.
The problem is with the relative path. If I replace the relative path with an absolute path, the path is resolved correctly and the image is displayed.
As I mentioned above, the control works fine in most cases. The one case where it isn't working is a Prism 2.1 project, where the control is instantiated on a user control in a Prism module. The module is a simple class library, but it has all of the references of a WPF project.
Any idea why the relative path would fail? Thanks in advance for your help.
I finally figured out the problem. It was actually in the C# backing class for my control. I declared an ImagePath property as a string, since that was how I was going to specify the image. Oops--bad call on my part. That property should actually be an ImageSource property, not a string. WPF has a built-in ImageSourceConverter class that will resolve the path and return the specified image. So, I simply changed the property name from ImagePath to Image, and changed its type from string to ImageSource. That solved the problem.
Thanks to Aviad P. for taking a crack at this. It was unsolvable without the C# code showing the property declarations. I'll post all code and markup next time.

Resources