Notifications
Clear all

[Closed] WPF in Max

I’ve started a blog where I posted a simple example of hosting something created with WPF inside of Max. Comments and questions welcomed.

http://apps.jhaywood.com/Blog

30 Replies

Awesome, Thanks for taking the time to share your research on this James, I fear I may have a fair few questions in the future!

Hey guys, just to remember you I did some tests some time ago and seeing what you guys are doing nowadays I thought this example would be very cool to show:

XamlReader=dotnetclass "System.Windows.Markup.XamlReader"
XamlString="<Window 
    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"
    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"
    Title=\"Window1\" Height=\"300\" Width=\"300\">
    <Grid>
        <Button Height=\"22\" HorizontalAlignment=\"Left\" Margin=\"12,12,0,0\" Name=\"Button1\" VerticalAlignment=\"Top\" Width=\"87\">Button</Button>
        <ComboBox Margin=\"0,12,12,0\" Name=\"ComboBox1\" Height=\"22\" VerticalAlignment=\"Top\" HorizontalAlignment=\"Right\" Width=\"122\" />
        <ListBox Margin=\"12,58,12,12\" Name=\"ListBox1\" />
    </Grid>
</Window>"
XamlWindow=XamlReader.Parse  XamlString
XamlWindow.Show()

This would be great for your Character Framework Pete!

Thanks for the info guys.

James – FYI it works for me in 2010 64bit on XP64. The visual style is different to your screenshot I believe due to being XP but I think you just need to have .NET 3.5 installed for it to work, at least for 2010. I seem to remember having a problem with someone’s WPF example in 2009 though.

1 Reply
(@jhaywood)
Joined: 11 months ago

Posts: 0

Thanks for pointing that out. I was getting an error in 2010 for some reason, and I know that Autodesk updated the .Net version for 2011, which is why I thought it just wouldn’t work. But I’ll try looking into it some more and update the blog post.

Hey Kameleon. I didn’t know about XamlReader. Thanks for pointing that out. I’ll have to look into it some more. But my first concern would be that this wouldn’t be a good way to create a more robust tool. While there is a lot you can do with pure Xaml, at a certain point you may need to add more functionality in the code behind file, add extra classes, etc., especially when it comes to interacting with Max using the MaxscriptSDK functions that Lone Robot has talked about.

But thanks again for bringing it up. I love finding new tools to play with.

FIY, here’s another way to create a WPF form (without the ElementsHost control):

dnWindow=dotnetobject "System.Windows.Window"
dnWindow.Title="WPF Test"
dnWindow.Height=200
dnWindow.Width=200

dnColor=dotnetobject "System.Windows.Media.SolidColorBrush"
dnColor.Color=(dotnetclass "System.Windows.Media.Colors").AliceBlue

dnCanvas=dotnetobject "System.Windows.Controls.Canvas"
dnCanvas.Background=dnColor

dnButton=dotnetobject "System.Windows.Controls.Button"
dnButton.Height=23
dnButton.Width=100
dnButton.Content="WPF Button Test"

dnCanvas.SetTop dnButton 10
dnCanvas.SetLeft dnButton 10

dnWindow.Content=dnCanvas
dnCanvas.Children.Add(dnButton)
dnWindow.Show()
1 Reply
(@jhaywood)
Joined: 11 months ago

Posts: 0

That works too. The nice thing about using a WPF window is that you can do some pretty cool things with it visually, like completely changing the shape and other nice effects.

The downside is that if you want it to act like it’s part of Max, you have to manage the owner and the windows background and foreground colors manually. But putting the control in a Rollout or MaxForm using ElementHost gets you those things for free. And a rollout even lets you dock it.

Just for fun, I tried the WPF window with my progress bar and works perfectly, with the caveats I’ve already mentioned.

dotNet.loadAssembly @"<folder name>\ProgressBar\ProgressBar\bin\Debug\ProgressBar.dll"
  
  bar = dotNetObject "ProgressBar.UserControl1"
  frm = dotnetobject "System.Windows.Window"
  
  frm.title = "Progress"
  frm.width = bar.width + 16
  frm.height = bar.height + 34
  frm.windowStartupLocation = frm.windowStartupLocation.centerScreen
  frm.windowStyle = frm.windowStyle.toolWindow
  
  frm.content = bar
  
  frm.show()
  
  -- set number of steps to use
  bar.steps = 50
  
  -- loop through the steps
  for i = 1 to bar.steps do
  (
  	-- force the UI to update
  	(dotNetClass "System.Windows.Forms.Application").DoEvents()
  	-- increment one step and change label
  	bar.DoStep()
  	bar.ProgressLabel = "Thing " + i as string
  	sleep .05
  )
  
  frm.close()
 PEN

Very cool guys. I need all the time in the world to keep up on all this stuff.

 PEN

I don’t see those issues as big ones. So write a dotNetLib that takes care of all those sorts of things when ever you use them.

Interesting to note that this will work in a rollout? Will it work in a rollout in the modifier panel and still allow event handlers or is that still out of scope?

4 Replies
(@jhaywood)
Joined: 11 months ago

Posts: 0

Yep, definitely not a blocking issue, but something to be aware of.

Here is what the rollout version would look like…

-- load the progress bar library
 dotNet.loadAssembly @"<folder location>\ProgressBar\ProgressBar\bin\Debug\ProgressBar.dll"
 
 -- load the WPF Integration library needed to create the ElementHost control
 dotNet.loadAssembly @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\WindowsFormsIntegration.dll"
 
 bar = dotNetObject "ProgressBar.UserControl1"
 size = [bar.width,bar.height]
 frm = rollout progressBar_RLT "Progress" width:size.x height:size.y
 (
 	dotNetControl eh "Integration.ElementHost" width:size.x height:size.y align:#left offset:[-14,-5]
 	
 	on progressBar_RLT open do
 	(
 		eh.child = bar
 	)
 )
 
 createDialog progressBar_RLT
 
 -- set number of steps to use
 bar.steps = 50
 
 -- loop through the steps
 for i = 1 to bar.steps do
 (
 	-- force the UI to update
 	(dotNetClass "System.Windows.Forms.Application").DoEvents()
 	-- increment one step and change label
 	bar.DoStep()
 	bar.ProgressLabel = "Thing " + i as string
 	sleep .05
 )
 
 destroyDialog progressBar_RLT

The only thing different is the creation of the rollout and then putting the controls inside of it. Note, I just figured out the you don’t really need the UserControl. Just put the ElementHost inside the rollout or window, and then the WPF control inside of that. I had the UserControl because I had originally created a generic “WPF host” control in C# which I was bringing into Max. But if you’re building it in Max to begin with, you don’t need it.

As far whether it would work in a modifier panel, I don’t know. It would just be another control in the rollout, so I’m assuming it would work the same as using it in a regular non-modifier rollout.

 PEN
(@pen)
Joined: 11 months ago

Posts: 0

Currently the issue with using dotNet controls in the modifier panel is with the scope of the event handlers. You are forced to write the events the same as you do for other Max UI items. Trying to add event handlers using dotNet.addEventHandlers does not work. I would assume the same issue is going to apply with WPF.

(@jhaywood)
Joined: 11 months ago

Posts: 0

Creating your tool with Visual Studio and compiling a dll that you would then load into the modifier should remove this limitation. Of course, relying on compiled components has it’s own drawbacks.

 PEN
(@pen)
Joined: 11 months ago

Posts: 0

Yes it would as you could then just use the standard event handlers in Max script. A bit of a pain for anything simple. Thanks for the suggestion though.

May i ask…what is WPF?

Cheers.

 PEN

Windows Presentation foundation. It is replacing GDI+, a quick google will get you way more information then can be posted here.

Page 1 / 3