WPF - Load Image in ListView - c#

i have a little problem with my WPF-Application.
Well, i have a ListView which shows at the first column a image. Each element can or cannot have a image, so from time to time i load a "default" image in this column.
Here is the problem.
When i load the default image, there is no image shown in the listview.
Here is the codepart, which adds the default image:
Uri src = new Uri(#"/myapp;component/Images/Picture.png", UriKind.RelativeOrAbsolute);
BitmapImage small_image_bmp = new BitmapImage();
small_image_bmp.BeginInit();
small_image_bmp.CacheOption = BitmapCacheOption.OnLoad;
small_image_bmp.UriSource = src;
small_image_bmp.EndInit();
small_image_bmp.Freeze();
dto.Bild1_Bitmap = small_image_bmp;
this.liste.Add(dto);
This code is not working.
But this part works very well:
Uri src = new Uri(#"C:\Users\me\Documents\Visual Studio 2010\Projects\myapp\myapp\Images\Picture.png", UriKind.RelativeOrAbsolute);
BitmapImage small_image_bmp = new BitmapImage();
small_image_bmp.BeginInit();
small_image_bmp.CacheOption = BitmapCacheOption.OnLoad;
small_image_bmp.UriSource = src;
small_image_bmp.EndInit();
small_image_bmp.Freeze();
dto.Bild1_Bitmap = small_image_bmp;
this.liste.Add(dto);
As you can see, the part who isnt working has a relative path and the code, who is working, has a absolute path.
But of course i cant use the absolute path...
Here is the XAML of the ListViewColumn:
<GridViewColumn Header="Bild">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="100" Height="100" Source="{Binding Bild1_Bitmap}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>

If code you posted for loading an image is in same assembly as of image. You can ignore component path and use like this - Images\Picture.png.
Also make sure image build action is set to Resource.

Related

Replace dynamically BitmapImage in Button (xaml)

I have following code snippet in xaml:
<UserControl x:Class="Ournamespace.OurClassName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
d:DesignHeight="250" d:DesignWidth="774" Loaded="UserControl_Loaded">
....
<Button Grid.Column="0" x:Name="Button_NewMarker" Style="{StaticResource ViewpointFlatButtonStyle}" Width="90" Height="65"
VerticalAlignment="Top" Click="Button_NewMarker_Click" x:FieldModifier="public" Margin="0,0,0,0" Grid.Row="1">
<BitmapImage UriSource="Icons/markers_add_disabled.png" />
</Button>
and I have tried to replace image on button dynamically, by loading new image
if( !imgCache.ContainsKey(path) )
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(path, UriKind.Relative);
bi.DownloadFailed += bi_DownloadFailed;
bi.DecodeFailed += bi_DecodeFailed;
bi.EndInit();
imgCache[path] = bi;
}
Button_NewMarker.BeginInit();
Button_NewMarker.Content = imgCache[path];
//Button_NewMarker.Content = oldbmp;
Button_NewMarker.EndInit();
There is no error occurring (overridden events for this)
and BitmapImage seems to be replaced - but for some reason it's grey.
Images are added to project as resources, and first image loaded seems to be working - but not dynamically replaced one.
I have tried also to use <Image ... > and even <Image ... <ImageBitmap - but all of them are not working - I suspect it has something to do with our control being UserControl.
What I have seen in internet - there is huge amount of recommendations of what and how should be done - I want now this to be done with absolute minimum amount of code - and preferably without using binding and templating. Binding can be proposed as second step after everything is done manually.
If image files are managed as resource files (i.e. project files which have their Build Action set to Resource) you should load them by a Resource File Pack URI.
Assuming a project folder Images with an image file Test.png:
var bi = new BitmapImage(new Uri("pack://application:,,,/Images/Test.png"));
Using the file name as key, the abobe would probably look like:
var path = "Test.png";
var uri = "pack://application:,,,/Images/" + path;
imgCache[path] = new BitmapImage(new Uri(uri));

how to clear image control from local path

i have a image control in wpf like this
<Image x:Name="Img" Source="{Binding IsAsync=True}" />
i set the image by fetching from a url like this
Img.DataContext = ImageUrl;
it shows fine and when i want to clear it i just use
Img.DataContext=null;
for the same control i have a browse button as well to select the image from local path like this
BitmapImage image = new BitmapImage(new Uri(path));
Img.Source=image;
now i want to clear that as well so i do
Img.Source=null;
after that the control wont show the image from url only local images can be opened
Edit: probably i need to set the binding again after making source to null, not sure how to do that
You are abusing bindings horribly. Please stop.
<Image x:Name="Img" Source="{Binding IsAsync=True}" />
Says "Bind to the data context", which isn't all that great. Bind to a property of your view model, something like:
<Image x:Name="Img" Source="{Binding Path=ImageLocation, IsAsync=True}" />
And then only ever change the image using ImageLocation. At the very least, only set it via the DataContext.
Once you set the source to a binding, you should never be changing it via code-behind. Period. Do that, and your problem will "magically" disappear, as you are doing it the right way now.
To clear image control, clear image url.
e.g imgControlName.ImageUrl = "";

How to Set ViewBox Image Source in Code Behind

In following a code sample here http://msdn.microsoft.com/en-us/library/ms752301(v=vs.110).aspx I'd like to be able to change the following XAML code to C# and set the ViewBox source in code behind. What is the proper method of doing this? Must I set the Child of the ViewBox?
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox MaxWidth="500" MaxHeight="500" Name="vb1">
<Image Source="tulip_farm.jpg"/>
</Viewbox>
</StackPanel>
The easiest way to achieve this is give a name to that specific image so you can set the source anywhere you want in code:
<Image x:Name="MyImage" Source="tulip_farm.jpg"/>
And in c#:
BitmapImage bitimg = new BitmapImage(new Uri(#"/MyNewLink.jpg", UriKind.Relative));
MyImage.Source = bitimg as ImageSource;

Binding an Image in WPF MVVM

I am having some trouble binding in Image to my viewmodel. I finally got rid of the XamlParseException, but the image does not come up. I even hard coded the image in the ViewModel. Can someone see what I am doing wrong?
View:
<Image HorizontalAlignment="Left" Margin="0,0,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Bottom" Grid.Row="8" Width="200" Grid.ColumnSpan="2" >
<Image.Source>
<BitmapImage DecodePixelWidth="200" UriSource="{Binding Path=DisplayedImage, Mode=TwoWay}" />
</Image.Source>
ViewModel:
string _DisplayedImagePath = #"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg";//string.Empty;
int _DisplayedImageIndex;
BitmapImage _DisplayedImage = null;
public BitmapImage DisplayedImage
{
get
{
_DisplayedImage = new BitmapImage();
if (!string.IsNullOrEmpty(_DisplayedImagePath))
{
_Rail1DisplayedImage.BeginInit();
_Rail1DisplayedImage.CacheOption = BitmapCacheOption.OnLoad;
_Rail1DisplayedImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
_Rail1DisplayedImage.UriSource = new Uri(_DisplayedImagePath);
_Rail1DisplayedImage.DecodePixelWidth = 200;
_Rail1DisplayedImage.EndInit();
}
return _Rail1DisplayedImage;
}
set
{
_Rail1DisplayedImage = value;
OnPropertyChanged("DisplayedImage");
}
}
Displaying an Image in WPF is much easier than that. Try this:
<Image Source="{Binding DisplayedImagePath}" HorizontalAlignment="Left"
Margin="0,0,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Bottom"
Grid.Row="8" Width="200" Grid.ColumnSpan="2" />
And the property can just be a string:
public string DisplayedImage
{
get { return #"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"; }
}
Although you really should add your images to a folder named Images in the root of your project and set their Build Action to Resource in the Properties Window in Visual Studio... you could then access them using this format:
public string DisplayedImage
{
get { return "/AssemblyName;component/Images/ImageName.jpg"; }
}
UPDATE >>>
As a final tip... if you ever have a problem with a control not working as expected, simply type 'WPF', the name of that control and then the word 'class' into a search engine. In this case, you would have typed 'WPF Image Class'. The top result will always be MSDN and if you click on the link, you'll find out all about that control and most pages have code examples as well.
UPDATE 2 >>>
If you followed the examples from the link to MSDN and it's not working, then your problem is not the Image control. Using the string property that I suggested, try this:
<StackPanel>
<Image Source="{Binding DisplayedImagePath}" />
<TextBlock Text="{Binding DisplayedImagePath}" />
</StackPanel>
If you can't see the file path in the TextBlock, then you probably haven't set your DataContext to the instance of your view model. If you can see the text, then the problem is with your file path.
UPDATE 3 >>>
In .NET 4, the above Image.Source values would work. However, Microsoft made some horrible changes in .NET 4.5 that broke many different things and so in .NET 4.5, you'd need to use the full pack path like this:
<Image Source="pack://application:,,,/AssemblyName;component/Images/image_to_use.png">
For further information on pack URIs, please see the Pack URIs in WPF page on Microsoft Docs.
If you have a process that already generates and returns an Image type, you can alter the bind and not have to modify any additional image creation code.
Refer to the ".Source" of the image in the binding statement.
XAML
<Image Name="imgOpenClose" Source="{Binding ImageOpenClose.Source}"/>
View Model Field
private Image _imageOpenClose;
public Image ImageOpenClose
{
get
{
return _imageOpenClose;
}
set
{
_imageOpenClose = value;
OnPropertyChanged();
}
}
#Sheridan thx.. if I try your example with "DisplayedImagePath" on both sides, it works with absolute path as you show.
As for the relative paths, this is how I always connect relative paths, I first include the subdirectory (!) and the image file in my project.. then I use ~ character to denote the bin-path..
public string DisplayedImagePath
{
get { return #"~\..\images\osc.png"; }
}
This was tested, see below my Solution Explorer in VS2015..
)
Note: if you want a Click event, use the Button tag around the image,
<Button Click="image_Click" Width="128" Height="128" Grid.Row="2" VerticalAlignment="Top" HorizontalAlignment="Left">
<Image x:Name="image" Source="{Binding DisplayedImagePath}" Margin="0,0,0,0" />
</Button>

Set ImageSource through ViewModel not working

I have a WPF application in which I use several images. Most of the images are set in the XAML-code as they will not change anymore. The Build Action of all my image-files are set to "Resource" and the Copy to Output Directory is set to "Do Not Copy". They are shown as expected, here's an example of how they are set:
<ribbon:RibbonApplicationMenu SmallImageSource="/Voetbal;component/Images/Ball_16.png">
//or
<ribbon:RibbonButton LargeImageSource="/Voetbal;component/Images/Calendar_32.png" />
//or
<Image Source="/Voetbal;component/Images/remove.png" Width="16" Height="16" />
But I also have images that have to be set throuch C#. In a UserControl I have a ListView which contains a certain column with following markup:
<GridViewColumn Header="" Width="32">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Icon}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The ItemsSource for the ListView is a Generic List that contains instances of items that will poulate the ListView. These items have two string-fields and an ImageSource (named 'Icon'). I set the Icon-property like this:
var icon = new BitmapImage(new Uri("/Images/Gold_16.png", UriKind.RelativeOrAbsolute));
myViewModel.Items[0].Icon = icon;
But the problem is that I don't see an image in the ListView. I have also tried following pieces of code. I have used these pieces from answers to similar questions here on SO and on other forums. It's not that I've been lazy or haven't tried anything but I can't figure out how to fix this...
var icon = new BitmapImage(new Uri("/Voetbal;component/Images/Gold_16.png", UriKind.RelativeOrAbsolute));
//or
var icon = new BitmapImage();
icon.BeginInit();
icon.UriSource = new Uri("pack://application:,,,/Voetbal;component/Images/Gold_16.png");
icon.EndInit();
//or
var icon = new BitmapImage();
icon.BeginInit();
icon.UriSource = new Uri("pack://application:,,,/Images/Gold_16.png");
icon.EndInit();
PS: I know the binding of my ViewModel works because the two string-properties are correctly shown in other columns in the ListView.
Does anyone know how I can set the ImageSource and bind it correctly to the ListView?
Thanks in advance!
myViewModel.Items[0].Icon = "Images/Gold_16.png";
Please try the above code. Make the Icon property to string

Categories

Resources