views:

28

answers:

1

How can I DataBind my Image control to automatically get the player.PlayerImage updates? As you can see from my code, I have tried to setup databinding, however it's not working.

Below is my current setup:

I have a CLR class called CDGPlayer that implements INotifyPropertyChanged.

The CDGPlayer class has a property called PlayerImage

private Image playerImage;
public Image PlayerImage
{
    get { return playerImage; }
    set
    {
        if (value != playerImage)
        {
            playerImage = value;
            NotifyPropertyChanged("PlayerImage");
        }
    }
}

I have a WPF client that I would like to use the CDGPlayer.

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:CDG="clr-namespace:GoldenKaraokeLib.CDG;assembly=GoldenKaraokeLib" 
    xmlns:local="clr-namespace:GoldenKaraokePlayerWPF" 
    x:Class="GoldenKaraokePlayerWPF.Window1"
    Title="Window1" Height="300" Width="654"
        x:Name="CDGPlayerHost" Loaded="CdgPlayerHostLoaded" Background="#FFCD6F6F">
    <Window.Resources>
        <local:CdgImageConverter x:Key="CDGImageConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.DataContext>
            <CDG:CDGPlayer x:Name="player"/>
        </Grid.DataContext>
        <Border BorderBrush="Black" BorderThickness="5">
            <Image x:Name="CDGImage" Source="{Binding PlayerImage, Converter={StaticResource CDGImageConverter}, UpdateSourceTrigger=PropertyChanged}"/>
        </Border>
    </Grid>
</Window>

in the Window1.cs file I have a Loaded event that calls the CDGPlayer class instance and invokes the Play method. This method generates a new System.Drawing.Image and stores it in PlayerImage.

I know the CDGImage Source property can not accept an System.Drawing.Image so I've attempted to write a crude converter. However, this is only called once on window load.

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    try
    {
        MemoryStream ms = new MemoryStream();
        Image bitmap = value as Image;
        BitmapImage bi = new BitmapImage();

        if (bitmap != null)
        {
            bitmap.Save(ms, ImageFormat.Bmp);

            bi.BeginInit();
            bi.StreamSource = ms;
            bi.EndInit();
        }

        return bi;
    }
    catch
    {
        return new BitmapImage();
    }
}

What am I doing wrong?

+1  A: 

Your binding appears to be correct when I try it. It looks like your converter has a bug, though. You don't rewind the stream, so BitmapImage will try to read starting from the end instead of starting from the beginning. Add a call to Stream.Seek:

if (bitmap != null)
{
    bitmap.Save(ms, ImageFormat.Bmp);
    ms.Seek(0, SeekOrigin.Begin); // Set position back to the start of the stream
    bi.BeginInit();
    bi.StreamSource = ms;
    bi.EndInit();
}
Quartermeister
This did the trick. Thank you!
Michael G