Situation
I'm trying to use an image control in my program that accesses an online image by binding it to a property.
XAML:
<Image Source="{Binding TheImage}" x:Name="imgPic" HorizontalAlignment="Left" Height="113" Margin="14,89,0,0" VerticalAlignment="Top" Width="120"/>
Specifically, I'm binding to the return value of the searchMembers method (which returns an object) mempic contains a URL, and this mempic will change depending on which member is currently logged in.
View Model:
public Uri TheImage
{
get
{
return new Uri(hillracing.searchMembers(Username).mempic);
}
}
Problem
Neither this code, or a static link to the image actually works.
Here is the test image I'm actually using
wondered if anyone could tell em what I was doing wrong.
thanks.
The WPF Image control is more sophisticated than you imagine... just use the string URI value as the Image.Source directly like this:
<Image Source="http://i.imgur.com/aIf7B0P.jpg" />
Or, if you want to data bind, do this:
<Image Source="{Binding TheImage}" ... />
...
public string TheImage
{
get { return "http://i.imgur.com/aIf7B0P.jpg"; }
}
Related
I am trying to create a WPF application with multiple small editors. One of these editors requires to load two images, enter a name in a TextBox and hit a save button.
In the code this does work flawless. The files are saved in a model and the image can be loaded. Before hitting the save button both of the images are actually shown in the editor. However after reopening (for editing) only one image is rendered.
I tested a bit around and found out that always the first image doesn't get rendered while the second does.
For example in the XAML it looks like this:
<Image Name="BackgroundImage" Grid.Row="1" Grid.Column="0" Source="{Binding Path=Background}" Width="120" Height="90"/>
<Image Name="ForegroundImage" Grid.Row="2" Grid.Column="0" Source="{Binding Path=Foreground}" Width="120" Height="90"/>
Here BackgroundImage doesn't get rendered, even though the property Background of the model has loaded the image successfully. If I were to swap these XAML Tags, meaning putting the ForegroundImage control above the BackgroundImage, then ForegroundImage doesn't get rendered while BackgroundImage does. Even if I don't change anything else like the Grid.Row or Column.
Then I tried to load the images in the code behind in the Loaded event handler of the window:
private void LocationEditor_OnLoaded(object sender, RoutedEventArgs e)
{
BackgroundImage.Source = ((Location)DataContext).Background;
ForegroundImage.Source = ((Location)DataContext).Foreground;
}
The same applies to this situation. Whichever line is executed first, won't be rendered in the Window.
In case it'll help, here's the code of the Background property (Foreground is built the same):
[JsonIgnore]
public BitmapImage Background
{
get
{
if (!string.IsNullOrWhiteSpace(BackgroundFile))
{
SetFree();
SetImage();
}
else
_background = null;
return _background;
}
}
The SetFree() method frees up memory resources if the image isn't needed anymore. This occurs when the window closes or whenever the BitmapImage is needed. (It'll reload the image each time in case the file of the image has changed.)
The SetImage() method does just one simple thing: Loading the image of the BackgroundFile image file and saves it in the _background field.
I don't quite know what the problem could be. I've tried out a few things but I don't work often with images while coding.
There must be something wrong with your SetFree() or SetImage() methods.
Fortunately you don't need the Background and Foreground properties in your view model at all, because WPF provides built-in automatic type conversion from string, Uri and byte[] to ImageSource. You can hence directly bind the Image's Source properties to the appropriate path properties in the view model:
<Image ... Source="{Binding BackgroundFile}"/>
<Image ... Source="{Binding ForegroundFile}"/>
For completeness, if you still wanted to have these properties, i'd suggest a simple implementation like shown below. Built-in image caching will take care that the file is not decoded more often than necessary:
public ImageSource Background
{
get
{
if (BackgroundFile != null)
{
try
{
return new BitmapImage(new Uri(BackgroundFile));
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
return null;
}
}
I'm trying to bind EmbeddedImages to a ListView so I can show a different icon depending on the item of the list. Using Working with Images tutorial I've managed to make a extension to show the embedded images, but only if i hard code the location to the icon.
So this works:
<Image Source="{local:ImageResource (namespace).icon.png}"/>
but I can't bind to the icon I want. I've tried all these and none worked:
<Image Source="{local:ImageResource {Binding _iconLocation}}" />
<Image Source="{Binding Source=local:ImageResource, Path=_iconLocation}"/>
If you want to use binding you don't need to use markup extension. Extension is done "Because there is no built-in type converter from string to ResourceImageSource".
In your model define
public ImageSource MyImageSource
{
get
{ //here you decide what resource to use
return ImageSource.FromResource("(namespace).icon.png");
}
}
Then in xaml use
<Image Source="{Binding MyImageSource}" />
And you don't need any extension classes
I am currently trying to get an image to show in design time in my Xaml with the code below:
Xaml:
<Canvas Grid.ColumnSpan="2" Margin="0,0,0,0">
<Image Canvas.ZIndex="1" Source="{Binding Coupon.OverlayImage}" Margin="0,-21,-76,108" Stretch="Fill" x:Name="PrintImageContextMenu" />
</Canvas>
C# Design Time:
Coupon.OverlayImage = Image.FromFile(#"C:\Temp\Images\TestImage.png");
Original Property of OverlayImage in VB (Legacy Code):
private _overlayImage as Image
Public Property OverlayImage As Image
Get
Return _overlayImage
End Get
Set
_overlayImage = value
NotifyPropertyChanged("OverlayImage")
End Set
End Property
Upon first view I cannot see anything wrong with but it does not show, even at runtime. Any ideas would be appreciated.
You can use Image Fallback value to set the default image.Here is a simple example.
<Window.Resources>
<BitmapImage x:Key="ImageSource" UriSource="C:\Temp\Images\TestImage.png"/>
</Window.Resources>
<Grid>
<Image
HorizontalAlignment="Left"
Source="{Binding SourceImage,FallbackValue={StaticResource ImageSource}}"/>
</Grid>
Everywhere you use the Image class, I think you use the System.Drawing.Image because the WPF Image control does not have a FromFile() method . You cannot use it as a source for the WPF Image Control. You must instead try using an IValueConverter to convert the Image to a BitmapSource/ImageSource.
Try this,
var uri = new Uri(Coupon.OverlayImage);
var bitmap = new BitmapImage(uri);
ImageName.Source = bitmap;
X problem:
I want to use vector graphic in WPF.
I have bunch of SVG files, which I can convert into XAML by using Inkscape. Resulting xaml is ResourceDictionary with ViewBox / Canvas containing Path, etc. Dictionaries are merged into App.xaml and I can use key to access them.
Question: how to use such images? It looks like I am not using them properly.
Here is how I am using them
<Viewbox Child="{StaticResource MyImageResourceKey}" Width="100" Height="100"/>
But it looks like I can use it only once (in one place)! Attempting to use that image in multiple places simultaneously will either remove it from previous place or will throw
System.ArgumentException: Must disconnect specified child from current parent Visual before attaching to new parent Visual.
Y problem
I want to show a list of vector images. I display them like this
<ItemsControl ItemsSource="{Binding Images}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Viewbox Width="100" Height="100">
<ContentPresenter Content="{Binding Image}"/>
</Viewbox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
ViewModel
public class ViewModelSomeWindow : INotifyPropertyChanged
{
public class MyImage
{
public object Image { get; set; }
}
private ObservableCollection<MyImage> _images;
public ObservableCollection<MyImage> Images
{
get { return _images; }
set { _images = value; OnPropertyChanged(); }
}
...
}
And items are added like this
Images.Add(new MyImage() { Image = App.Current.Resources["MyImageResourceKey"] });
Problem: when using same image ("MyImageResourceKey") for second item, then first item displays (blank) image. If image is already displayed with the use of StaticResource somewhere, then adding item will throw above ArgumentException.
P.S.: I need to solve Y problem, but perhaps I am not using vector graphic properly.
Please Use x:shared =false in path as shown in attached image
and visit this link too for reference
I am having a little bit of trouble binding the back end to the front end image. The image is dynamic. Here is the code on the back end that serves the front end:
public string currentCardImage
{
get
{
return currentCard.imageSource;
}
}
and the front end XAML for this is:
<Image Name="ImageMain"
Source="{Binding currentCardImage}"
HorizontalAlignment="Left"
Height="100"
Margin="368,529,0,0"
Grid.Row="1"
VerticalAlignment="Top"
Width="100"
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<CompositeTransform Rotation="90.203" />
</Image.RenderTransform>
</Image>
Unfortunately this is not working. I can verify that there is data loaded into the currentCard and thus imageSource returns a location of the image.
Please let me know if you need more information. Any help is greatly appreciated!
EDIT: The c# code is in the XAML code behind
The reason why your binding fails is that Bindings are, by default, to the instance held within the DataContext property. So, the binding
{Binding currentCardImage}
actually means
this.DataContext.currentCardImage
Since you say the property is in the codebehind, I'm assuming your code looks something like this:
public sealed class MyClass : Window
{
public string currentCardImage
{
get { // SNIP!
In order to bind to this property, you have to redirect the binding to look to the root of the xaml tree (your Window) to start looking for the specified path.
The easiest way to do this is to name your root element
<Window x:Class="HerpDerp"
HideOtherAttributesBecauseThisIsAnExample="true"
x:Name="thisIsTheBindingTarget">
<!-- snip -->
and tell your Binding to look there
{Binding currentCardImage, ElementName=thisIsTheBindingTarget}