-1

The question has now been answered in a comment.

Original question:

The following is not enough:

this.Background = Brushes.Yellow;
RenderTargetBitmap bmp = new RenderTargetBitmap(...);
Measure(...);
Arrange(...);
bmp.Render(this);

If the color was different before this code being executed, the color is still the old color instead of changing to yellow.

So what step am I missing?

(It does work if I add an await Task.Delay(100); before rendering it, but seems to be an ugly workaround.)

ispiro
  • 26,556
  • 38
  • 136
  • 291
  • Depends on what your control is doing with its Foreground. Does it override OnRender and draw something? – Clemens Apr 23 '23 at 18:03
  • @Clemens. It does nothing. Absolutely nothing. The control isn't even rendered, I just use it to create the bitmap. – ispiro Apr 23 '23 at 18:04
  • It does nothing with the Freground? Then it's hard to understand what exactly you are asking. – Clemens Apr 23 '23 at 18:05
  • Do your changes are rendered? on changing the foreground – Ahmed Alayat Apr 23 '23 at 18:06
  • @AhmedAlayat I'm not rendering it. Just creating the control in order to create a bitmap. – ispiro Apr 23 '23 at 18:07
  • @Clemens Changed now to `Background` - imagine just a green rectangle. Now I change to yellow but the bitmap is a **green** rectangle. – ispiro Apr 23 '23 at 18:08
  • 1
    You may try to call UpdateLayout or InvalidateVisual in addition to Measure and Arrange. – Clemens Apr 23 '23 at 18:11
  • can you please post your code? i've already got your point but maybe there is something else that prevent your code from being executed as expected – Ahmed Alayat Apr 23 '23 at 18:12
  • Also try to move measure and arrange code before creating the bmp instance and after changing the background – Ahmed Alayat Apr 23 '23 at 18:29
  • @Clemens UpdateLayout did the trick. You can convert that into an answer. Thanks! – ispiro Apr 23 '23 at 18:36
  • Measure and Arrange are both updating the layout asynchronously: after the method call the code continues execution e.g. rendering the bitmap. UpdateLayout forces a synchronous Measure and Arrange which is why it should be avoided in general. – BionicCode Apr 23 '23 at 18:52
  • @BionicCode But that is exactly why it helps here, because I need it to be done before the rendering. – ispiro Apr 23 '23 at 18:54
  • I know. I was just explaining why it helps or why your original code isn't working as expected. Isn't the control a child of the element tree? It shouldn't be necessary to call Measure and Arrange explicitly. By the way, calling Measure is enough. Arrange will be called implicitly after Measure has completed. Calling Measure *and* Arrange results in poor performance because Arrange is then executed twice. – BionicCode Apr 23 '23 at 19:03
  • @BionicCode Thanks. So it seems from your comment that calling UpdateLayout means I don't even have to call either (Measure or Arrange) explicitly. – ispiro Apr 23 '23 at 19:25
  • First of all you should generally avoid calling those layout methods explicitly as they are very expensive. Usually the framework handles the layout and calls those methods. Those methods are `InvalidateMeasure`, `InvalidateArrange`, `UpdateLayout`, `Measure` and `Arrange`. `InvalidateMeasure` and `InvalidateArrange` set a flag that the layout is dirty and needs recalculation. The framework decides when to call `Measure` and/or `Arrange` but *both* are called (deferred). – BionicCode Apr 23 '23 at 20:47
  • Calling `Measure` *always* results in a call to `Arrange` (full layout pass). So `InvalidateMeasure` will result in full layout pass. `InvalidateArrange` will result in only `Arrange` being called. `Measure` and `Arrange` result in an asynchronous layout pass. So does `InvalidateMeasure` and `InvalidateArrange`. `UpdateLayout` also results in a full layout pass (`Measure` and `Arrange` are called successively), but this time the layout pass is executed synchronously. – BionicCode Apr 23 '23 at 20:47
  • When you call `InvalidateMeasure` you don't need to call `InvalidateArrange` because when calling `Measure` the framework automatically calls `Arrange` afterwards. `UpdateLayout` is basically a synchronous wrapper around a call to the otherwise asynchronous `Measure` and `Arrange`. – BionicCode Apr 23 '23 at 20:47

1 Answers1

0

[posting a temporary answer until the commenter posts their own.]

The problem was solved in a comment - adding UpdateLayout before rendering the Visual to the bitmap was enough.

ispiro
  • 26,556
  • 38
  • 136
  • 291