WPF cannot implicitly convert system.drawing.bitmap to media.brush - c#

I want to change the background of a button manually in my WPF app.
I have an image imported into my resources and I want to do:
MyButton.Background = MyProject.Properties.Resources.myImage;
But I get the error:
cannot implicitly convert system.drawing.bitmap to media.brush
How can I do this??

You should read about brushes first here.
And then use ImageBrush, something like this:
MyButton.Background = new ImageBrush(...);
(or, maybe, put the brush into resources...)
UPDATE
You can find how to create imageSource from bitmap easilly. for example, here. Like:
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
MyButton.Background = new ImageBrush(bitmapSource);

In a WPF application, you do usually not add image resources as you did in WinForms.
Instead you add the image file directly to your Visual Studio project, just like any other file. If there are multiple images, it may make sense to put them in a subfolder of the project (e.g. called "images"). The Build Action of that file has to be set to Resource (which is the default for image files).
Now you can create a BitmapImage from a Pack URI to that file.
Finally you create an ImageBrush from the BitmapImage to set the Background property.
var uri = new Uri("pack://application:,,,/images/myImage.jpg");
var image = new BitmapImage(uri);
MyButton.Background = new ImageBrush(image);

Related

Xamarin Forms XAML - Unable to create multiple images from a list of URLs

I have a List where the string is the url of an image.
I am trying to dynamically create a grid of images with the source being each url.
I have tried binding but it doesn't seem to work. I also cannot access the x:Name of an image I created in Xaml. I am open to doing this in Xaml or in the code behind.
Any ideas of how to do this.
//imageList is a List<string> with your image urls in it
foreach(var i in imageList) {
Image image = new Image();
image.Source = ImageSource.FromUri(new Uri(i));
// you will need to add logic to calculate the Row/Column for each image
myGrid.Children.Add(image,x,y);
}

folder missing in resources

I have the following code for showing an image:
Image im = new Image();
im.Source = new BitmapImage(new Uri("Icons.login.jpg", UriKind.RelativeOrAbsolute));
im.Height = 200;
im.Width = 200;
icons.Add(new IconImagesForDummies() { Name = str, Image = im });
The Image class belongs to System.Windows.Controls.Image. I have added a folder to store images separately from Resources folder (named Icons). But I have set the build action property of all images to Embed Resource and they have been set to Copy Always. I do not know why I can not see the images. I'm using WPF. During debugging I found out that the image path was fine and it founded that, but I do not know the reason, the image was not showed. I have read here but was useless.
Is there something wrong with the Uri?
EDIT: maybe its just this simple
im.Source = new BitmapImage(new Uri(#"Icons\login.jpg", UriKind.Relative));
Edit: changing build action to content works.

DirectoryNotFoundException when creating a BitmapImage

I develop an IOC framework in the form of a DLL that creates the application's main window and displays various WPF Pages in it. There is a folder of PNG images with their Build Action set to Resource. I use code like this to set the sources of WPF Image elements...
MyImage.Source = new BitmapImage(new Uri("/MyAssembly;component/Images/MyImage.png", UriKind.Relative));
This works great. However, there is also a feature where the user can choose to display one of these WPF Pages in a separate window. Here is the mystery: If the user navigates to the page in the main window before showing it in a separate window, all is well. However, if the user shows the page in a separate window before it is shown in the main window, I get a DirectoryNotFoundException saying " Could not find a part of the path 'C:\MyAssembly;component\Images\MyImage.png'."
I discovered the OnLoad cache option and tried the following code...
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri("/MyAssembly;component/Images/MyImage.png", UriKind.Relative);
image.EndInit();
MyImage.Source = image;
However, I then get the DirectoryNotFoundException on the very first image that I attempt to create.
I also tried an absolute URI...
MyImage.Source = new BitmapImage(new Uri("pack://application:,,,/MyAssembly;component/Images/MyImage.png", UriKind.Absolute));
I then get a UriFormatException saying "Invalid URI: Invalid port specified."
I solved the problem by using the 'pack' URI format as shown in the question. However, I needed to make a call to the Application class before I did so. This has the effect of executing the Application's static constructor which registers the 'pack' URI scheme. I found my answer here. The call I used was simply this:
var app = Application.Current;

How to show Image from byte array in Microsoft report

I am using a Report file and a ReportViewer control to show a report which loads data dynamically from objects during run-time.
I need to show an image which is stored as a byte array in the object.
The PictureBox's value is currently set to:
=First(Fields!ImageData.Value, "dtstItemImage")
And I set the DataSource using:
ImageBindingSource.DataSource = this.item.Image.ImageData;
The code compiles and runs but the image is not displayed in the report.
Is this because the PictureBox needs to be bound to an Image object (and not to a byte array)? Or are there perhaps some properties of the PictureBox which I need to set?
UPDATE 1
I've added a border to the PictureBox just to make sure that's its visible and it does show up in the report. It just doesn't contain the image.
UPDATE 2
I've fixed a mistake in my code. I've changed:
ImageBindingSource.DataSource = this.item.Image.ImageData;
to:
ImageBindingSource.DataSource = this.item.Image;
as the PictureBox is bound to the ImageData field BUT the DataSource is the Image object.
Now I get a small cross icon instead of nothing which (at least for me) indicates some progress but I don't know where the byte[]-bitmap conversion code needs to be.
I managed to solve this by setting the report's Image box Source property to Database (it was previously set to External).
More info about the different available Source values can be found at (MSDN) HowTo: Add an Image (Reporting Services).
You need to create an image object from the byte array and use that as the source.
To do this, you can use a helper function like the following
public static Image LoadImage(byte[] imageBytes)
{
Image image = null;
using (var ms = new MemoryStream(imageBytes))
image = Image.FromStream(ms);
return image;
}
Edit
For WPF, you need to use BitmapSource (MSDN) instead of Image (MSDN)
public static BitmapSource LoadImage(Byte[] imageBytes)
{
var image = new BitmapImage();
using (var ms = new MemoryStream(binaryData))
{
image.BeginInit();
image.StreamSource = ms;
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
}
if (image.CanFreeze)
image.Freeze();
return image;
}
NB: You can could also do this using a IValueConverter, see this blog post for the source code.
and then modify your data binding
ImageBindingSource.DataSource = LoadImage(item.Image.ImageData);
...
Make sure that the image (and MemoryStream) is disposed properly when you finished with it, as otherwise you will leak memory.
Also, depending on the format of your byte array you may need to do some work. See one of my question/answers for some helpful information.

Image.Source (with binding) is blocking image file after binding is removed

In a GridView, I've templated the items so an Image control inside that template receives an Uri using a binding (also tried with BitmapImage) to show a picture file. It works, but I cannot delete those files because those files are blocked. Even if I clear the collection feeding the GridView.ItemsSource, and even if I call GC.Collect(), they are still blocked.
Thanks to Philip for his working suggestion... as I used a Converter to feed a BitmapImage to every Image control, found some particular things had to do to make it work, and here it is for future reference:
InMemoryRandomAccessStream Ras = new InMemoryRandomAccessStream();
var archivo = CartoonsDownloader.FolderImagenes.GetFileAsync(TheFileName);
var fileStream = CartoonsDownloader.FolderImagenes.OpenStreamForReadAsync(TheFileName);
fileStream.Result.CopyTo(Ras.AsStreamForWrite());
BitmapImage MapaDeBits = new BitmapImage();
// Even it's RANDOM, I have to manually "Seek" it at 0.
Ras.Seek(0);
MapaDeBits.SetSource(Ras);
MapaDeBits.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
return MapaDeBits;
This could be a bug in the XAML stack (so you could report it on MSDN forums), or just a side effect of its nature of caching images. As an alternative - you can open the file yourself and set the image using the SetSource method. Then you should have better control over the file access.

Categories