Brandon
Brandon

Reputation: 945

WritableBitmap to ImageSource in MVVM

END GOAL: To print a 2D barcode using WPF and MVVM:

BACKGROUND INFO (Probably not relevant) I have two projects in my solution. One project controls my business logic, and the second project controls the printing logic, creation and printing of labels. I am using named pipes for IPC. I am using MVVM and have a Xaml Template to design the label and at run time I fill its properties and print it. This is all working correctly.

MORE INFO: (Might be relevant) I am using a third party library that creates 2D barcodes. This is working and the call to make the barcode returns a Writable Bitmap

ISSUE: I am trying to databind the writable bitmap to the Image control on my template.

public void FooBar(string[] LabelProperties)
{
    try
    {
        BarcodeWriter writer = new BarcodeWriter()
        {
           Format = BarcodeFormat.PDF_417,
           Options = new ZXing.Common.EncodingOptions
           {
              Height = 50,
              Width = 132,
              Margin = 0
           }
        };

        var wb = writer.Write("Some String");

        System.Windows.Controls.Image newImage = new System.Windows.Controls.Image()
        {
           Height = 50,
           HorizontalAlignment = HorizontalAlignment.Left,
           Name = "image",
           Stretch = Stretch.None,
           VerticalAlignment = VerticalAlignment.Top,
           Width = 132,
           Source = wb,
        };

        this.BarCodeImage = newImage;
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message.ToString().Trim());
    }
}

Its worth noting that I cannot directly place the WritableBitmap to the BarCodeImage.Source

this.BarCodeImage.Source = wb;

because I'm using the MVVM design, the BarCodeImage isn't instantiated so if I try to set something to its Source, it is throws a null reference.

The XAML in the template

<Image Height="50" 
       HorizontalAlignment="Left" 
       Margin="10,2,0,0" 
       Name="image" 
       Stretch="None" 
       VerticalAlignment="Top" 
       Width="132" 
       Source="{Binding lblBarCodeImage}" />

My Thought Because I am having to instantiate a new Controls.Image() and then setting that to the BarCodeImage it is breaking this somehow.

Other Things I can show the other classes and settup to prove my MVVM is settup correctly, but all the other controls are databinding correctly - though they are all strings that I am databinding - no other Image controls.

I have also tried converting the WritableBitmap into a byte array and tried using this solution, but that also did not work

Upvotes: 0

Views: 2338

Answers (2)

Clemens
Clemens

Reputation: 128136

Do not not create an Image control in code behind!

Instead, declare a view model property of type ImageSource and in XAML bind the Image control's Source property to that view model property.

View Model:

public class YourViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ImageSource barCodeImage;

    public ImageSource BarCodeImage
    {
        get { return barCodeImage; }
        set
        {
            barCodeImage = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("BarCodeImage"));
        }
    }

    ...
}

XAML:

<Image ... Source="{Binding BarCodeImage}"/>

In code behind, assign the WriteableBitmap to the BarCodeImage property:

yourViewModel.BarCodeImage = wb;

Upvotes: 3

Kikootwo
Kikootwo

Reputation: 380

You should have a property of BitmapImage like so:

    private BitmapImage photoSelected;

    public BitmapImage PhotoSelected
    {
        get { return photoSelected; }
        set { photoSelected = value; OnPropertyChanged("PhotoSelected"); }
    }

Then on the action that you desire you do this:

PhotoSelected = new BitmapImage(new Uri(@"pack://application:,,,/Images/4.png"));

Replace /Images/4.png with the path to your image starting at the solution level. For example, this is what my solution tree looks like to reach that point:

Solution Tree

XAML Used for binding:

<Image x:Name="BitMapImage" Source="{Binding PhotoSelected, Mode=TwoWay}" RenderOptions.BitmapScalingMode="HighQuality"/>

Upvotes: 0

Related Questions