eupton
eupton

Reputation: 221

Bind Image in DataTemplate to System.Drawing.Image

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

Upvotes: 1

Views: 4220

Answers (1)

eupton
eupton

Reputation: 221

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}}" />

Upvotes: 1

Related Questions