Reputation: 945
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
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
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:
XAML Used for binding:
<Image x:Name="BitMapImage" Source="{Binding PhotoSelected, Mode=TwoWay}" RenderOptions.BitmapScalingMode="HighQuality"/>
Upvotes: 0