2

I'm creating a WPF project using Python Tools for Visual Studio (in VS 2010). I add an Image control to the form. I click the "..." in the Image's Source property, and find an image.

This adds an "Images" folder to the project (both in the filesystem and in the solution), and copies the image to that folder (again both in the filesystem and in the solution). The image does not show up in the "Add" dialog. The Source attribute is set to "Images/foo.png".

In the XAML the source is blue-underlined because the "Build Action" is not set to "Resource". The only build actions available are "Content", "Compile", and "None". I presume "Resource" isn't available in a dynamic language like IronPython (certainly an embedded resource would be complex). I don't know whether this is the problem or whether this can be ignored.

The image does not show in the live editing window, and it doesn't show when the program runs.

I've tried "/Images/foo.png" (as suggested here), "pack://application:,,,/foo.png", "pack://application:,,,/Images/foo.png", "pack://siteoforigin:,,,/foo.png", and "pack://siteoforigin:,,,/Images/foo.png".

(The siteoforigin doesn't work because the 'origin' is ipy.exe. If I move the Images folder to the folder where IronPython is installed, then this does work. Obviously not a great solution!).

I've tried moving the Images folder in the filesystem to the same folder as the solution (i.e. one level up in the hierarchy), and having the image in the same folder as the .py file rather than in an Images subfolder.

If I change the source (directly in the XAML) to an absolute path, then it works perfectly. Obviously this isn't a great solution either!

How can I use a relative path for the Image?

Community
  • 1
  • 1
Tony Meyer
  • 10,079
  • 6
  • 41
  • 47

2 Answers2

3

It is possible. Apparently all you need to do is specify the source as a BitmapImage and relative URI will use the current directory as the base. Ignore the warnings about the file not being a resource, it doesn't really matter. It will show when you run your program.

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Title="MyWpfApplication" Height="300" Width="300">
    <Grid>
        <Image>
            <Image.Source>
                <BitmapImage UriSource="../Relative/Path/To/Image.png" />
            </Image.Source>
        </Image>
    </Grid>
</Window> 

I think it is all due to the default value converters for images. If you bypass using them, it all seems to just work out.

Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
  • This does indeed work, although the image doesn't display in the designer (only when the application is run). – Tony Meyer Nov 09 '11 at 21:55
2

The best way I found to deal with image paths is to just completely bypass that ponderous pack:// URI nonsense and simply use a Binding that binds directly to a BitmapImage.

<Image Source="{Binding imgWarningYellow}" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center" />

This way, I can use a simple GetFullPath filesystem call in code to locate the damn thing and load it up as a BitmapImage:

yellowbitmap = System.Windows.Media.Imaging.BitmapImage()
yellowbitmap.BeginInit()
yellowbitmap.UriSource = System.Uri(System.IO.Path.GetFullPath("Images\warning-yellow50.png"))
yellowbitmap.DecodePixelHeight = 50
try:
    yellowbitmap.EndInit()
except System.IO.FileNotFoundException as e:
    print e.Message
else:
    self.imgWarningYellow = yellowbitmap
Aphex
  • 7,390
  • 5
  • 33
  • 54
  • I suspect it's me doing something wrong, but I couldn't get this to work. I copied exactly this code (except for the filename). I tried with the code before and after the wpf.LoadComponent call. The program would run, but the image doesn't display. – Tony Meyer Nov 09 '11 at 22:10
  • Check the path to the image. The GetFullPath call takes a relative path and prepends the current working directory - which is the directory your startup file is in. The startup file is the .py file you run to start your program - in Visual Studio, it's the file with the green "play" icon on it. – Aphex Nov 09 '11 at 23:09
  • Also, I neglected to mention that after assigning the BitmapImage to the `self.imgWarningYellow` property at the end, an `INotifyPropertyChanged` event is raised to refresh the binding. In my code, `self.imgWarningYellow` happens to be [a special property that raises that notification automatically](http://gui-at.blogspot.com/2009/11/inotifypropertychanged-in-ironpython.html), but you may have to explicitly do so. – Aphex Nov 09 '11 at 23:51