Posted By James Haywood

I recently came across a nasty issue that comes up when hosting a WPF control inside of a docked Max rollout.  The problem is that anything that causes the entire Max UI to redraw (like docking/undocking a rollout or changing the minimized state of the Graphite ribbon while it's docked) makes the WPF control completely disappear.  The elements of the control pop back into existence as you mouse over them, but of course it's a pain to have to keep waving your arrow over a section of the screen to get your controls back.

Fortunately, there's a fairly easy work around to keep it from disappearing.

So, execute the following script and you'll see a row of WPF buttons in a stackpanel docked to the left side of the screen like so...

WPF refresh issue 1

dotNet.loadAssembly @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsFormsIntegration.dll"

rollout wpfRefresh_RLT "" width:70 height:220
  dotNetControl eh "Integration.ElementHost" width:70 height:500 align:#left offset:[-14,-5]
   on wpfRefresh_RLT open do
     uc = dotNetObject "System.Windows.Controls.UserControl"
     eh.child = uc
     sp = dotNetObject "System.Windows.Controls.StackPanel"
     for i = 1 to 10 do
       btn = dotNetObject "System.Windows.Controls.Button"
       btn.height = 20
       btn.content = "button " + i as string
       sp.children.add btn
     uc.content = sp

createDialog wpfRefresh_RLT style:#(#style_toolwindow,#style_sysmenu,#style_resizing)
cui.RegisterDialogBar wpfRefresh_RLT style:#(#cui_floatable,#cui_dock_left,#cui_handles)
cui.DockDialogBar wpfRefresh_RLT #cui_dock_left

And now if you do something to make the UI redraw, like I mentioned above, you get this...

WPF refresh issue 2

Wave the mouse arrow over the controls and you'll see them reappear one at a time.

The way to keep this from happening is to catch the Paint event on the ElementHost and manually force it to redraw by calling it's Refresh() method.  That's easy enough, but it turns out that calling Refresh() causes the Paint event to trigger again.  So it gets into a nice little infinite loop and really messes with Max's overall performance.

So we need to add one more step, which is to use a boolean variable to make sure that it only refreshes once and then stops.

Add the following to the rollout to make these changes:

local doRefresh = true

on eh Paint args do

    if doRefresh then
       doRefresh = false
       doRefresh = true

Now the WPF control will redraw itself whenever it needs to.  The full script can be downloaded here.

2 Comment(s):
reform said...
There should be a name for situations like this.... when you post a question that you've been struggling with for a long time, and then when you post the question, you immediately discover the solution yourself! It seems that my problem was that my form was a "UserControl". Changing this to a "ContainerControl" appears to fix the issue without causing any other unwanted effect. Perhaps I should have double check I'd tried the other options in the thread that led me to this page in the first place! Thanks goes to Pen for the solution.
March 7, 2014 4:40 PM
reform said...
Hi James, Thanks for posting this! I had this issue and your code does fix the problem. Unfortunately it introduces a new problem... when my form refreshes it causes my vrayFB to lose focus and to disappear entirely. I don't suppose you've also come across this problem and found a solution? I'm a bit stuck now, either I live with my vrayFB disappearing but I retain the contents of my form, or I lose my form and I keep the vrayFB in focus. Any suggestions appreciated!
March 7, 2014 4:33 PM
Leave a Comment:
Name: * Email: *
Home Page URL:
Comment: *
   char left.

Enter the text shown in the image on the left: *
 Remember Me?
* fields are requried


User Profile
James Haywood
Seattle, WA


You have 545284 hits.