1

I am attempting to bind Image.Source in a DataTemplate to a System.Drawing.Image as discussed here: using XAML to bind to a System.Drawing.Image into a System.Windows.Image control

<UserControl.Resources>
    <media:ImageConverter x:Key="imageConverter" />
    <DataTemplate DataType="{x:Type data:GameTile}" >
        <StackPanel Orientation="Vertical" Margin="5" Background="Transparent">
            <Viewbox>
                <TextBlock FontWeight="Bold" Text="{Binding PointValue}" TextAlignment="Center" FontSize="14" />
            </Viewbox>
            <Image Margin="0,5,0,0" Source="{Binding Path=Image.Image, Converter={StaticResource imageConverter}}" />
        </StackPanel>
    </DataTemplate>
</UserControl.Resources>
    <Grid>
        <loop:ListBox x:Name="listBox1" 
                         ItemsSource="{Binding Path=GameModel.Game.GameTiles}"
                         ItemContainerStyle="{StaticResource GameTileContainerStyle}" Orientation="Vertical" />
    </Grid>

The GameTile object has an Image (not a system.drawing.image) property that points to a Picture object which has an Image property of type System.Drawing.Image. I am binding the ItemsSource on the ListBox to a GameTiles Collection on a Game object.

Objects

public class Game
{
    public XPCollection<GameTile> GameTiles
    {
        get { return GetCollection<GameTile>("GameTiles"); }
    }
}

public class GameTiles
{
    Picture fImage;
    public Picture Image
    {
        get { return fImage; }
        set { SetPropertyValue<Picture>("Image", ref fImage, value); }
    }
}

public class Picture
{

    private FileData fFile;
    public FileData File
    {
        get { return fFile; }
        set
        {
            SetPropertyValue("File", ref fFile, value);
            if (string.IsNullOrEmpty(fName))
            {
                fName = (value == null ? string.Empty : value.FileName);
            }
            fImage = null;
        }
    }

    Image fImage;
    public System.Drawing.Image Image
    {
        get 
        {
            if (fImage == null)
            {
                try
                {
                    MemoryStream stream = new MemoryStream();
                    fFile.SaveToStream(stream);
                    stream.Position = 0;
                    fImage = Image.FromStream(stream);
                }
                catch 
                { 
                    //TODO: log exception
                }
            }
            return fImage;
        }
        //set { SetPropertyValue<Image>("Image", ref fImage, value); }
    }
}

The images are not showing up in the ListBoxItems, but any other property that I bind to in the DataTemplate will show up. It may be worth noting that I am using Devexpress Xpo as an ORM. Also the classes represented above do implement INotifyPropertyChanged. Any thoughts on what I may be missing?

EDIT: Forgot to mention that I have implemented a value converter as mentioned in the post that I linked to above. However, if I put a breakpoint in the converter method, it is never called.

EDIT: Added the fFile property to the code above. I can set an Image.Source to the GameTile.Image.Image property through c#(by converting it to BitmapImage), and have it work as expected, but I'm not sure how to accomplish that with a DataTemplate through c#. I would prefer to set the binding in XAML, but would settle for a c# workaround with a DataTemplate (or something else that would work). I am pretty confident that the issue is not with the GameTile.Image property pulling image from the database because if I manually set the source on an Image.Source in c#, the image is there. It simply isn't working in the DataTemplate.

Edit: Determined the issue to be related to properties that are not directly on the DataType that I am binding to for example with and GameTile has a (int)PointValue property, a (Picture object)Image property, and a (Prize object)Prize property.

If I bind to

<TextBlock Text="{Binding PointValue}" /> 

it works as expected. But if I bind to

<TextBlock Text="{Binding Prize.Name}" /> 

it does not work. And If I bind to

<Image Margin="0,5,0,0" Source="{Binding Image.BitmapImage}" />

it fails also. The following graphic shows the error that is being thrown by the binding.

BindingExpression path error: 'Name' property not found on 'object' ''XPCollection' (Hash=...)'. BindingExpression:Path=Prize.Name; DataItem=GameTile' (HashCode=...); target element is 'TextBlock'(Name=''); target property is 'Text' (type 'String')

enter image description here

Thanks, Eric

Community
  • 1
  • 1
eupton
  • 221
  • 2
  • 10
  • Perhaps you add some code to the catch block `//TODO: log exception`. – Clemens Oct 19 '12 at 08:53
  • 1
    If you load the image from a stream, why don't you directly load a BitmapImage by its [StreamSource](http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapimage.streamsource.aspx) property? You could change the type of your `Image` property to [ImageSource](http://msdn.microsoft.com/en-us/library/system.windows.media.imagesource.aspx) and wouldn't need any converter. – Clemens Oct 19 '12 at 08:57
  • what exactly are you doing in your converter? if your "Image.Image" is returning a "Stream" (byte array) then you don't need any converter you can directly bind it to ImageSource. If you are using converter, that converter should return a "BitmapImage". – Bathineni Oct 19 '12 at 11:09
  • Could you show the fFile-Property/Field and the code where you manipulate it? – Florian Gl Oct 19 '12 at 11:23
  • @Clemens: The catch block isn't the issue. I've set a break point here that never gets hit. And the image property has a value, I'm just not sure I'm binding it correctly. – eupton Oct 19 '12 at 16:16
  • @Clemens: I am not converting to BitmapImage here, because wpf is not the primary interface that uses these objects. We have an existing WinForms and Web interface that would require rewriting. I do appreciate your feedback on this though. – eupton Oct 19 '12 at 16:21
  • @bathineni: The Converter is exactly the same as the solution found in the linked question at the top of my post. – eupton Oct 19 '12 at 16:22
  • @Clemens thanks for the suggestion on changing the Image property to a BitmapImage directly on my business object to prevent the need for a converter. Although I couldn't change the existing property I did use your suggestion and created a new property that returns a BitmapImage and I bind directly to it. – eupton Nov 06 '12 at 15:32

1 Answers1

1

Found the solution. Had to change this:

<TextBlock Text="{Binding Prize.Name}" /> 

to this:

<TextBlock Text="{Binding Prize!.Name}" /> 

The only difference is the exclamation point(!). This also worked for the image property.

<Image Margin="0,5,0,0" Source="{Binding Path=Image!.Image, Converter={StaticResource imageConverter}}" />
eupton
  • 221
  • 2
  • 10