2

I'm playing around with fractals as a private project to practice (to leave beginner level^^). I have a canvas holding an image, which is bound to a WriteableBitmap:

<Canvas Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="1" Grid.RowSpan="1" Name="RenderCanvas" Background="LightCyan">
  <Image Name="RenderImage" Source="{Binding Path=RenderBitmap}" Stretch="Fill" Height="{Binding Path=BitmapHeight, Mode=OneWayToSource}" Width="{Binding Path=BitmapWidth, Mode=OneWayToSource}"/>
</Canvas>

My viewmodel class currently looks like this:

public class MainViewModel : ViewModelBase  
{
  #region private fields
  private int _bitmapheight;
  private int _bitmapwidth;
  private WriteableBitmap _renderbitmap = new WriteableBitmap(500, 500, 96, 96, PixelFormats.Bgr32, null);
  #endregion

  #region public properties
  public int BitmapHeight
  {
  get { return _bitmapheight; }
  set { SetProperty<int>(ref _bitmapheight, value); }
  }
  public int BitmapWidth
  {
    get { return _bitmapwidth; }
    set { SetProperty<int>(ref _bitmapwidth, value); }
  }
  public WriteableBitmap RenderBitmap
  {
    get { return _renderbitmap; }
    set { SetProperty<WriteableBitmap>(ref _renderbitmap, value); }
  }
  #endregion

  #region Constructors
  public MainViewModel ()
  {
  }
  #endregion

  #region public Methods
  public void updateRenderBitmap(int size, int destX, int destY)
  {
    Int32Rect rect = new Int32Rect(0, 0, size, size);
    byte[] sourcebuffer = new byte[size * size * 4];
    for(int currentbyte = 0; currentbyte < sourcebuffer.Length;   currentbyte++)
    {
      sourcebuffer[currentbyte] = 255;
    }
    int stride = size * 4;
    _renderbitmap.WritePixels(rect, sourcebuffer, stride, destX, destY);
  }
  #endregion
}

So just to test if everything works so far I called the update method from the MainWindow.xaml.cs:

  public MainWindow()
  {
    InitializeComponent();
    MainViewModel vm = (MainViewModel)this.DataContext;
    vm.updateRenderBitmap(250, 125, 125);
  }

Turns out, everything works as expected, I have my Canvas with the set Background, inside of it a black square from the WriteableBitmap, and within that the white square I updated:

Screenshot However, there are two questions I have so far:

  1. As you can see, there is a red border around the image. I don't really know where it comes from, but I want to remove it.
  2. Currently, I initialize the _renderbitmap with a fixed set number. However, I want it to have the size of the RenderImage, which is bound to BitmapWidth and BitmapHeight. But I can't use those apparently, because they are not static - if I make them static I can use them, but they still have the value 0 during the instantiation.
dymanoid
  • 14,771
  • 4
  • 36
  • 64
Roland Deschain
  • 2,211
  • 19
  • 50
  • May it be a validation border? Try something like `Validation.SetErrorTemplate(this.RenderImage,null);` in your code,just to see it the red border goes away – Pikoh May 07 '18 at 09:49
  • 1
    `Width="{Binding Path=BitmapWidth, Mode=OneWayToSource}"` (and also the Height Binding) does not make sense. What is it supposed to do? Width and Height are `NaN` unless you set them. – Clemens May 07 '18 at 09:51
  • @Clemens with `Width="{Binding Path=BitmapWidth, Mode=OneWayToSource}"` I wanted to get the image width and height to the properties of my viewmodel class. However, I see that's not working. – Roland Deschain May 07 '18 at 09:55
  • First the properties should be `double`, not `int`. Then you would bind them to `ActualWidth` and `ActualHeight`. And don't call them `BitmapWidth`and `BitmapHeight` because that implies a pixel size, which it isn't. – Clemens May 07 '18 at 09:57
  • @Pikoh Thanks, that fixed it. Have to read up, what it does. – Roland Deschain May 07 '18 at 09:59
  • I also doubt that it is good design to have a view model that knows about the rendered size of an image in a view. Better let the view transform coordinates to the actual size of the bitmap in the view model. – Clemens May 07 '18 at 09:59
  • Note also that instead of disabling validation errors, you should better fix your Bindings. – Clemens May 07 '18 at 10:02
  • 1
    If that solved it, check your code as it must be throwing a validation error. – Pikoh May 07 '18 at 10:02
  • @Clemens of course. My advice was only to check if it was a validation error, now OP should check the code to see why :) – Pikoh May 07 '18 at 10:03
  • Actually, Binding the Width and Height of the image threw the validation error. – Roland Deschain May 07 '18 at 10:05
  • Well, and ActualWidth and ActualHeight can't be bound... I'd seriously suggest not to have these Bindings at all. – Clemens May 07 '18 at 10:08
  • @clemens "I also doubt that it is good design to have a view model that knows about the rendered size of an image in a view" - I'm not entirely sure what you mean by that. Also later on I will need to know the actual size of the image, because I have to assign pixels to coordinates to calculate the mandelbrot set (which is the goal of this exercise) – Roland Deschain May 07 '18 at 10:08
  • @RolandDeschain That's ok, but it should be done in the view, not in the view model. The view could for example easily calculate relative coordinates in the interval `0..1`, which the view model could use for its calculations. – Clemens May 07 '18 at 10:10
  • @Clemens OK, thanks for the help! – Roland Deschain May 07 '18 at 10:11

1 Answers1

2

The reason for the red border is validation errors, resulting from the non-working Bindings

Width="{Binding Path=BitmapWidth, Mode=OneWayToSource}"

and

Height="{Binding Path=BitmapHeight, Mode=OneWayToSource}" 

These Bindings produce errors because the values of the Width and Height properties are double.NaN when they aren't set explicitly.

You shouldn't have these Bindings at all. Instead of having a view model that knows about the rendered size of an image, it would be better to pass logical coordinates (e.g. in the interval 0 .. 1) to the view model.

Clemens
  • 123,504
  • 12
  • 155
  • 268